diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..bdb0cab --- /dev/null +++ b/.gitattributes @@ -0,0 +1,17 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore index 57a1574..5357cbd 100644 --- a/.gitignore +++ b/.gitignore @@ -194,3 +194,10 @@ FakesAssemblies/ # Visual Studio 6 workspace options file *.opt + +# NSIS output +/ScriptForInstaller/Output/ + +# Bass DLL +!/DoubanFM.Bass/x86/ +!/DoubanFM.Bass/x64/ \ No newline at end of file diff --git a/DoubanFM.Bass/Bass.Net.dll b/DoubanFM.Bass/Bass.Net.dll new file mode 100644 index 0000000..569c12c Binary files /dev/null and b/DoubanFM.Bass/Bass.Net.dll differ diff --git a/DoubanFM.Bass/Bass.Net.xml b/DoubanFM.Bass/Bass.Net.xml new file mode 100644 index 0000000..360ef6e --- /dev/null +++ b/DoubanFM.Bass/Bass.Net.xml @@ -0,0 +1,64185 @@ + + + + Bass.Net + + + + + Provides general methods to detect beats live in an audio signal and to calculate the resulting Beats Per Minute (BPM). + Requires: bass.dll - available @ www.un4seen.com. + + + The BPMCounter class is an internal implementation of the BASS.NET API and does not require any additional extension or add-on to the BASS audio library, meaning only bass.dll is required. + However, must have been called before using any method within this class! + NOTE: When using the BPMCounter class with an already existing decoding channel (created with the BASS_STREAM_DECODE flag) the data will be retrieved from that channel, meaning the data will be 'stolen'. + So it is NOT recommended to use this class with any decoding streams. + Internally the algo is based on human ear simulation - meaning an average energy history of 1 second is used, since this is what the human ear can keep - so the BPM results might change and vary more often as with systems scanning the whole file or bigger parts of it. + The advantage is therefore that this system might be used with live data and has a fast reaction time of about 1 second only - like our human ear. + The typical use of this class is as followed: + a) create an instance of this class (e.g. at the beginning of your application) + b) use a timer callback (e.g. every 20ms or every 25ms) to process the audio signal (the timer frequency must be specified when creating the class instance). + c) in the timer callback call to detect a beat. + d) retrieve the propertiy to get the calculated Beats Per Minute value. + You should call the method whenever you play another stream or if the returned BPM looks completely wrong. + There are also methods to calculate the BPM manually using a TAP click button. E.g. call on a mouse click event to tap (set) a beat manually and call to retrieve the manually tapped BPM value. + Beat detection is a very very complex task and it is almost impossible to implement it matching for any kind of audio signal. So please note, that it might NOT work with all tracks in the same way - with some tracks it might return really bad results. + This implementation is a 'simple' one (not needing too much CPU power). It is based on instant energy calculation on 128 frequency bands and comparing them with it's average engery for that band. + The variation of the energy of each frequency band is used as a dynamic sensitivity factor. The peak detector uses an attack time of 0ms and there is a dynamic release envelop for the release time - plus we have a Schmitt triggers and a rising edge detectors implemented for each frequency band. + The low pass frequency has a fixed value of 350Hz (for detecting bass drums) and the mid range frequency is set to be between 1500Hz and 4000Hz (to detect e.g. snare drums). This to calculate an overall trigger value for all frequency bands. + Finally there is a Schmitt trigger again to detect the final beat for each call to the audio signal processing. + You might notice, that often more beats are detected as you would recognize them with your ear (when doing manual tapping). These are intermediate beats or simply lound noise in the signal (which the algo did not filter good enough). + So the BPM calculation uses a time spotting approximation to determine when a beat is a good beat to count. 'No-good' beats are simply not counted. So it sometimes might take some time until the live BPM value reaches a good value! + The default BPM value range is between 60 and 180 BPM. But this might be changed using the or properties. + Note: 1 BPM is worth about 5ms (at 120BMP) - or in other words: if your time intervall differs in 5ms the resulting BPM might have a difference of about 1 BPM. + Therefor we use a BPM history buffer which we interleave and calculate the average to equalize this effect. + The BPM results are not equally good for all music tracks and genres. However, beat detection and BPM calculation is mostly needed for DJ applications with music having mostly clear and distinct beats and for this kind of music the class produces very good results. + Also keep in mind, that when working with highly compressed or equalized tracks (e.g. badly encoded MP3 tracks) the quality might also suffer - so for best results use good audio material. + + + + + The contructor of the beat detection class. + + The frequency of your timer callback in milliseconds (how often you will call ), e.g. 20ms. + The samplerate of the audio signal to process. You might also change this with calling at any time later. + + + + Call this to set (tap) a beat manually (e.g. on a mouse click event). + The resulting (tapped) BPM value is available at . + + + + + Call this to reset all internal buffers and/or to change the current samplerate of the audio signal to be processed. + + The new samplerate (specify -1 to leave the current one). + You should at best call this method every time you play a new track. + But you might also call this method if the calculated BPM is wrong and you wanted to give it a fresh try. + + + + Call this method to change the current samplerate of the audio signal to be processed. + + The new samplerate which should be used when processing audio sample. + + + + Processes the audio data (gets instant FFT samples) and calculates the live BPM. + + The channel who's audio signal should be processed to detect a beat. + Set this to , if you want the method to return only the counted BPM beats. If set to each detected beat will be returned. + , if a beat was detected or , if no beat was detected. + This is the main method doing the beat detection and live BPM calculation. Call this method in your timer callback as frequently as possibly (e.g. every 20ms is a good value, but every 50ms should also be okay). + Note: it is important, that you call this method in fixed time intervalls! The more often you call this method (the smaller your timer intervall is) the more exact will be the resulting BPM value. + You must also call this method in the same interval as specified when you created the class instance. + Since beat detection is very complex this method might return incorrect values when using it with audio signals containing a lot of noise. + The method internally uses some history buffers, which needs first to be filled. So it will take around 1 second (or around 50 calls at 20ms) before you receive first results! + Also note, that the internal buffer is flushed at certain intervals, so give the method some time to result newer and even 'better' values, especially, if the audio signal starts with different beats at the track beginning or has intermediate parts with no or different beats. + You might also use this method to detect a given beat (e.g. to perform automatic mixing) and so to determine a good mixer start point (cue point). + Note: This method might return 'intermediate' detected beats - so the detected beats might not always reflect your listening experiance like when using manual tapped beats. So with very slow jams (e.g. at 70 or 80bpm) the resulting BPM might sometimes be twice at high. + The method itself takes less than 1ms to perform it's task. Internally the algo is based on human ear simulation - meaning an average energy history of 1 second is used, since this is what the human ear can keep - so the BPM results might change and vary more often as with systems scanning the whole file or bigger parts of it. + The advantage is therefore that this system might be used with live data and has a fast reaction time of about 1 second only - like our human ear. + Note: 1 BPM is worth about 5ms (at 120BMP) - or in other words: if your time intervall differs in 5ms the resulting BPM might have a difference of about 1 BPM. + Therefor we use a BPM history buffer which we interleave and calculate the average to equalize this effect. + + + + private int _stream; + // create a BPMCounter instance, the timer will be fired every 20ms + private BPMCounter _bpm = new BPMCounter(20, 44100); + ... + // create a stream + _stream = Bass.BASS_StreamCreateFile(_fileName, 0, 0, BASSFlag.BASS_DEFAULT); + // get the samplerate of that stream + BASS_CHANNELINFO info = new BASS_CHANNELINFO(); + Bass.BASS_ChannelGetInfo(_stream, info); + // and start playing the and also start the BPM counter + if (_stream != 0 && Bass.BASS_ChannelPlay(_stream, false) ) + { + //playing... + _bpm.Reset(info.freq); + // start our bpm timer callback + this.timerBPM.Start(); + } + + private void timerBPM_Tick(object sender, System.EventArgs e) + { + if ( _stream == 0 || Bass.BASS_ChannelIsActive(_stream) != BASSActive.BASS_ACTIVE_PLAYING) + { + this.timerBPM.Stop(); + return; + } + bool beat = _bpm.ProcessAudio(_stream, true); + if (beat) + { + // display the live calculated BPM value + this.labelBPM.Text = _bpm.BPM.ToString( "#00.0" ); + } + } + + + Private _stream As Integer + ' create a BPMCounter instance, the timer will be fired every 20ms + Private _bpm As New BPMCounter(20, 44100) + ... + ' create a stream + _stream = Bass.BASS_StreamCreateFile(_fileName, 0, 0, BASSFlag.BASS_DEFAULT) + ' get the samplerate of that stream + Dim info As New BASS_CHANNELINFO() + Bass.BASS_ChannelGetInfo(_stream, info) + ' and start playing the and also start the BPM counter + If _stream <> 0 AndAlso Bass.BASS_ChannelPlay(_stream, False) Then + 'playing... + _bpm.Reset(info.freq) + ' start our bpm timer callback + Me.timerBPM.Start() + End If + + Private Sub timerBPM_Tick(sender As Object, e As System.EventArgs) + If _stream = 0 OrElse Bass.BASS_ChannelIsActive(_stream) <> BASSActive.BASS_ACTIVE_PLAYING Then + Me.timerBPM.Stop() + Return + End If + Dim beat As Boolean = _bpm.ProcessAudio(_stream, True) + If beat Then + ' display the live calculated BPM value + Me.labelBPM.Text = _bpm.BPM.ToString("#00.0") + End If + End Sub + + + + + + Gets or Sets the BPM history buffer size (Minimum=2, Maximum=50, Default=10). + + The BPM history buffer is used to keep the last detected BPM values. The resulting final value is calculated as the average value of the history. + Setting a new BPM history buffer size value will also reset the last calculated BPM values. Setting the BPM history buffer size to an even number is a good idea. + + + + + Gets or sets the minimum BPM value (default is 60, minimum is 30). + + + + + Gets or sets the maximum BPM value (default is 180, maximum is 250). + + + + + Gets or sets the currently detected live BPM value (detected via ). + + + + + Gets or sets the manually tapped BPM value (detected via ). + + + + + Provides a Win32 high performance counter. + + + This class is very simple to use. Just create an instance of , call to start timing and call to stop timing. + To retrieve the elapsed time, just call the method and you will get the elapsed time in seconds. + + + + // create a new HiPerfTimer object + HiPerfTimer pt = new HiPerfTimer(); + pt.Start(); // start the timer + // the code to be timed + Console.WriteLine("Test"); + pt.Stop(); // stop the timer + // print the duration of the timed code + Console.WriteLine("Duration: {0} sec", pt.Duration); + + + ' create a new HiPerfTimer object + Dim pt As New HiPerfTimer() + pt.Start() ' start the timer + Console.WriteLine("Test") ' the code to be timed + pt.Stop() ' stop the timer + ' print the duration of the timed code + Console.WriteLine("Duration: {0} sec", pt.Duration) + + + + + + Default constructor to create a high performance counter. + + The HiPerfTimer is not supported on this platform. + + + + Start the timer. + + + + + Stop the timer. + + + + + Returns the duration of the timer (in seconds). + + + + + BASS.NET API wrapper for BASS_VST.DLL + Requires: bass_vst.dll - VST plugin support Add-On. + + + BASS_VST allows the usage of VST effect plugins as well as VST instruments (VSTi plugins) with BASS. + VST PlugIn Technology by Steinberg Media Technologies GmbH. + (C) Bjoern Petersen Software Design'n'Development, Hamburg, Germany. + Contact: drsilver@silverjuke.net - www.silverjuke.net. + Redistribution of this package is allowed if all files stay intact. + However, there is no guarantee, that all VST plugins might really work - just try them out. + BASS_VST is VST host compatible up to the new VST 2.4 implementation and (hopefully) implements all needed features - + incl. the new double precision processing. + Note that BASS_VST only loads realtime VST effects with at least 1 Input and 1 Output (stereo effects will typically have at least 2 In and 2 Out). + While the normal usage is very easy (only one function - - is really needed), + BASS_VST also allowed advanced usage of the VST features - incl. embedding an editor or subclassing the whole library. + + + + + NOT used - all members are static! + + + + + + + + + + + + + + + Assigns a VST effects (defined by a DLL file name) to any BASS channels. + This overload implements the Unicode overload for the dllFile name, so the BASS_UNICODE flag will automatically be added if not already set. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. Or 0, if you want to test, if the dll is a valid VST plugin. + The fully qualified path and file name to the VST effect plugin (a DLL file name). + A combination of these flags (see ): + + BASS_VST_KEEP_CHANSBy default, mono effects assigned to stereo channels are mixed down before processing and converted back to stereo afterwards. Set this flag to avoid this behaviour in which case only the first channel is affected by processing. + BASS_UNICODEdllFile is Unicode (16-bit characters) (not needed here, since the overloads already take care of it). + + + Same meaning as for - DSPs with higher priority are called before those with lower. + On success, the method returns the new vstHandle that must be given to all the other functions, else 0 is returned. Use to get the error code. + The VST plugin is implemented via a DSP callback on the channel. That means when you play the channel (or call if it's a decoding channel), the sample data will be sent to the VST effect at the same time. + If the channel is freed all DSPs are removed automatically, also all VST DSPs are removed as well. If you want or need to free the VST DSP manually you can call . + For testing if a DLL is a valid VST effect, you can set chan to 0 - however, do not forget to call even in this case. + You may safely assign the same DLL to different channels at the same time - the library makes sure, every channel is processed indepeningly. But take care to use the correct vstHandles in this case. + Finally, you can use any number of VST effects on a channel. They are processed alongside with all other BASS DSPs in the order of it's priority. + To set or get the parameters of a VST effect you might use alongside with and to enumerate over the total number of effect parameters. + To retrieve details about an individual parameter you might use . + If the VST effect supports an embedded editor you might also invoke this one with . If the embedded editor also supports localization you might set the language in advance with . + If you need to temporarily bypass the VST effect you might call - will tell you the current bypass status though. + Use to get even more details about a loaded VST plugin. + + + + // create any stream + int stream = Bass.BASS_StreamCreateFile(_fileName, 0, 0, BASSFlag.BASS_SAMPLE_FLOAT); + // and assign a VST effect + int vstHandle = BassVst.BASS_VST_ChannelSetDSP(stream, + "C:\\VstPlugins\\DelayEditGUI.dll", BASSVSTDsp.BASS_VST_DEFAULT, 1); + // and play the stream + Bass.BASS_ChannelPlay(stream, false); + ... + // if the VST effect is not needed anymore... + BassVst.BASS_VST_ChannelRemoveDSP(stream, vstHandle); + + + ' create any stream + Dim stream As Integer = Bass.BASS_StreamCreateFile(_fileName, 0, 0, BASSFlag.BASS_SAMPLE_FLOAT) + ' and assign a VST effect + Dim vstHandle As Integer = BassVst.BASS_VST_ChannelSetDSP(stream, + "C:\VstPlugins\DelayEditGUI.dll", BASSVSTDsp.BASS_VST_DEFAULT, 1) + ' and play the stream + Bass.BASS_ChannelPlay(stream, False) + ... + ' if the VST effect is not needed anymore... + BassVst.BASS_VST_ChannelRemoveDSP(stream, vstHandle) + + + + + + Removes a VST effect from a channel and destroys the VST instance. + + The channel handle from which to remove the VST effect... a HSTREAM, HMUSIC, or HRECORD. + The VST effect handle as returned by . + If successful, is returned, else is returned. Use to get the error code. + + If you do not call explicitly and you have assigned a channel to the effect, the effect is removed automatically when the channel handle is deleted by BASS (like for any other DSP as well). + For various reasons, the underlying DLL is unloaded from memory with a little delay, however, this has also the advantage that subsequent adding/removing of DLLs to channels has no bad performance impact. + + + + + + + + + + + + + + + Creates a new BASS stream based on any VST instrument plugin (VSTi). + This overload implements the Unicode overload for the dllFile name, so the BASS_UNICODE flag will automatically be added if not already set. + + The sample rate of the VSTi output (e.g. 44100). + The number of channels... 1 = mono, 2 = stereo, 4 = quadraphonic, 6 = 5.1, 8 = 7.1. + The fully qualified path and file name to the VSTi plugin (a DLL file name). + Any combination of these flags (see ): + + BASS_SAMPLE_FLOATProduce 32-bit floating-point output. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. Note this only applies to playback of the mixer's output - the mixing of the source channels is always performed by BASSmix. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D streams must be mono (chans=1). The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_FXrequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + + + If successful, the new vst handle is returned, else 0 is returned. Use to get the error code. + On success, the function returns the new vstHandle that must be given to + the other functions. The returned VST handle can also be given to the typical BASS_Channel* functions. + Use to deletes and free a VST instrument channel. + + + + Deletes and frees a VST instrument channel. + + The VSTi channel to delete (as created by ). + If successful, is returned, else is returned. Use to get the error code. + + Note, that you cannot delete VST effects assigned to this channels this way; for this purpose, please call . + + + + + Sends a MIDI message/event to the VSTi plugin. + + The VSTi channel to send a MIDI message to (as created by ). + The Midi channel number to use (0 to 15). + The Midi event/status value to use (see for details). + The data bytes to send with the message (use to compose a data byte 1 and 2). + If successful, is returned, else is returned. Use to get the error code. + + Use one of the commands similar to . + Set to 0xFFFF and to the raw command to send. + The raw command must be encoded as 0x00xxyyzz with xx=MIDI command, yy=MIDI databyte #1, zz=MIDI databyte #2. should be set to 0 in this case. + + Send SysEx commands by setting to 0xEEEE. + will denote the type of event to send (see about possible values for in such case). + + + + + using Un4seen.Bass.AddOn.Vst; + using Un4seen.Bass.AddOn.Midi; + + int vstHandle = BassVst.BASS_VST_ChannelCreate(44100, 2, "yourVSTi.dll", BASSFlag.BASS_DEFAULT); + Bass.BASS_ChannelPlay(vstHandle); + BassVst.BASS_VST_ProcessEvent(vstHandle, 0, BASSMIDIEvent.MIDI_EVENT_NOTE, Utils.MakeWord(60, 100)); + + + Imports Un4seen.Bass.AddOn.Vst + Imports Un4seen.Bass.AddOn.Midi + + Dim vstHandle As Integer = BassVst.BASS_VST_ChannelCreate(44100, 2, "yourVSTi.dll", BASSFlag.BASS_DEFAULT) + Bass.BASS_ChannelPlay(vstHandle) + BassVst.BASS_VST_ProcessEvent(vstHandle, 0, BASSMIDIEvent.MIDI_EVENT_NOTE, Utils.MakeWord(60, 100)) + + + + + + Sends a SysEx or MIDI (short)message/event to the VSTi plugin. + + The VSTi channel to send a MIDI message to (as created by ). + The pointer to your Midi message data to send (byte[]). + The length of a SysEx message or 0 in case of a normal Midi (short)message. + If successful, is returned, else is returned. Use to get the error code. + + To send a Midi (short)message : + The raw message must be encoded as 0x00xxyyzz with xx=MIDI command, yy=MIDI databyte #1, zz=MIDI databyte #2. should be set to 0 in this case. + + To send a SysEx message: + must be set to a pointer to the bytes to send and must be set to the number of bytes to send. + + + + + + Sends a SysEx or MIDI (short)message/event to the VSTi plugin. + + The VSTi channel to send a MIDI message to (as created by ). + The byte array containing your Midi message data to send. + The length of a SysEx message or 0 in case of a normal Midi (short)message. + If successful, is returned, else is returned. Use to get the error code. + + To send a Midi (short)message : + The raw message must be encoded as 0x00xxyyzz with xx=MIDI command, yy=MIDI databyte #1, zz=MIDI databyte #2. should be set to 0 in this case. + + To send a SysEx message: + must be set to a pointer to the bytes to send and must be set to the number of bytes to send. + + + + + + Sends a MIDI (short)message to the VSTi plugin. + + The VSTi channel to send a MIDI message to (as created by ). + The already constructed MIDI short message to send. + If successful, is returned, else is returned. Use to get the error code. + + + + Sends a MIDI system exclusive message to the VSTi plugin. + + The VSTi channel to send a MIDI message to (as created by ). + The already constructed MIDI system exclusive message to send. + If successful, is returned, else is returned. Use to get the error code. + Do NOT prepare the message with ! + + + using Un4seen.Bass.AddOn.Vst; + using Un4seen.Bass.AddOn.Midi; + + int vstHandle = BassVst.BASS_VST_ChannelCreate(44100, 2, "yourVSTi.dll", BASSFlag.BASS_DEFAULT); + Bass.BASS_ChannelPlay(vstHandle); + + // create a new system-exclusive message + MidiSysExMessage sysex = new MidiSysExMessage(false, IntPtr.Zero); + // message will be 8 byte (incl. SoX and EoX) + sysex.CreateBuffer(8); + // write start-of-system-exclusive + sysex.MessageWriteSoX(); + int offset = 1; + // write 6 more bytes... + sysex.MessageWrite8(ref offset, 65); + sysex.MessageWrite16(ref offset, 1023); + sysex.MessageWrite16(ref offset, 13); + sysex.MessageWrite8(ref offset, 1); + // write end-of-system-exusive + sysex.MessageWriteEoX(); + + BassVst.BASS_VST_ProcessEvent(vstHandle, sysex); + + + Imports Un4seen.Bass.AddOn.Vst + Imports Un4seen.Bass.AddOn.Midi + + Dim vstHandle As Integer = BassVst.BASS_VST_ChannelCreate(44100, 2, "yourVSTi.dll", BASSFlag.BASS_DEFAULT) + Bass.BASS_ChannelPlay(vstHandle) + + ' create a new system-exclusive message + Dim sysex As New MidiSysExMessage(False, IntPtr.Zero) + ' message will be 8 byte (incl. SoX and EoX) + sysex.CreateBuffer(8) + ' write start-of-system-exclusive + sysex.MessageWriteSoX() + Dim offset As Integer = 1 + ' write 6 more bytes... + sysex.MessageWrite8(offset, 65) + sysex.MessageWrite16(offset, 1023) + sysex.MessageWrite16(offset, 13) + sysex.MessageWrite8(offset, 1) + ' write end-of-system-exusive + sysex.MessageWriteEoX() + + BassVst.BASS_VST_ProcessEvent(vstHandle, sysex) + + + + + + Returns the number of editable parameters for the VST effect. + + The VST effect handle as returned by . + The number of editable parameters or if the effect has no editable parameters, 0 is returned. + + To set or get the individual parameters of a VST effect you might use alongside with and to enumerate over the total number of effect parameters. + To retrieve details about an individual parameter you might use . + If the VST effect supports an embedded editor you might also invoke this one with . If the embedded editor also supports localization you might set the language in advance with . + + + + + Get the value of a single VST effect parameter. + + The VST effect handle as returned by . + The index of the parameter (must be smaller than ). + on success. + + All VST effect parameters are in the range from 0.0 to 1.0 (float), however, from the view of a VST effect, they may represent completely different values. + E.g. some might represent a multiplier to some internal constants and will result in number of samples or some might represent a value in dB etc. + You can use to get further information about a single parameter, which will also present you with the current value in a readable format. + + + List all parameters and values of a loaded VST effect: + + // assign and load the VST effect + vstHandle = BassVst.BASS_VST_ChannelSetDSP(_stream, + "C:\\VstPlugins\\DelayEditGUI.dll", BASSVSTDsp.BASS_VST_DEFAULT, 1); + // get the total number of parameters + int vstParams = BassVst.BASS_VST_GetParamCount(vstHandle); + // create a paramInfo object + BASS_VST_PARAM_INFO paramInfo = new BASS_VST_PARAM_INFO(); + for (int i=0; i<vstParams; i++) + { + // get the info about the parameter + float paramValue = BassVst.BASS_VST_GetParam(vstHandle, i); + Console.WriteLine( paramValue.ToString() ); + + // and get further info about the parameter + BassVst.BASS_VST_GetParamInfo(vstHandle, i, paramInfo); + Console.WriteLine( paramInfo.ToString() ); + } + + + ' assign and load the VST effect + vstHandle = BassVst.BASS_VST_ChannelSetDSP(_stream, + "C:\VstPlugins\DelayEditGUI.dll", BASSVSTDsp.BASS_VST_DEFAULT, 1) + ' get the total number of parameters + Dim vstParams As Integer = BassVst.BASS_VST_GetParamCount(vstHandle) + ' create a paramInfo object + Dim paramInfo As New BASS_VST_PARAM_INFO() + Dim i As Integer + For i = 0 To vstParams - 1 + ' get the info about the parameter + Dim paramValue As Single = BassVst.BASS_VST_GetParam(vstHandle, i) + Console.WriteLine(paramValue.ToString()) + + ' and get further info about the parameter + BassVst.BASS_VST_GetParamInfo(vstHandle, i, paramInfo) + Console.WriteLine(paramInfo.ToString()) + Next i + + The output from the above might look like this: + + 0,5 + Delay = 22049 samples + 0,5 + FeedBack = 0.500000 amount + 0,75 + Volume = -2.49877 dB + + + + + + Set a value of a single VST effect parameter. + + The VST effect handle as returned by . + The index of the parameter (must be smaller than ). + The new value to set in the range from 0.0 to 1.0 (float). See the documentation of the actual VST implementation for details of the effective value representation. + on success. + + All VST effect parameters are in the range from 0.0 to 1.0 (float), however, from the view of a VST effect, they may represent completely different values. + E.g. some might represent a multiplier to some internal constants and will result in number of samples or some might represent a value in dB etc. + So it is a good idea to call after you modified a parameter, in order to to get further information about the parameter in question, which will also present you with the current value in a readable format. + + + + // assign and load the VST effect + vstHandle = BassVst.BASS_VST_ChannelSetDSP(_stream, + "C:\\VstPlugins\\DelayEditGUI.dll", BASSVSTDsp.BASS_VST_DEFAULT, 1); + + // create a paramInfo object + BASS_VST_PARAM_INFO paramInfo = new BASS_VST_PARAM_INFO(); + // set a parameter with index number 1 to 0.7 + BassVst.BASS_VST_SetParam(vstHandle, 1, 0.75); + // and get the info about the parameter back, so that we know how is looks like in a readable format + BassVst.BASS_VST_GetParamInfo(vstHandle, i, paramInfo); + Console.WriteLine(String.Format( "{0} = {1} {2}", paramInfo.name, paramInfo.display, paramInfo.unit)); + // this might look like this: "Volume = -2.49877 dB" + + + ' assign and load the VST effect + vstHandle = BassVst.BASS_VST_ChannelSetDSP(_stream, + "C:\VstPlugins\DelayEditGUI.dll", BASSVSTDsp.BASS_VST_DEFAULT, 1) + + ' create a paramInfo object + Dim paramInfo As New BASS_VST_PARAM_INFO() + ' set a parameter with index number 1 to 0.7 + BassVst.BASS_VST_SetParam(vstHandle, 1, 0.75) + ' and get the info about the parameter back, so that we know how is looks like in a readable format + BassVst.BASS_VST_GetParamInfo(vstHandle, i, paramInfo) + Console.WriteLine([String].Format("{0} = {1} {2}", paramInfo.name, paramInfo.display, paramInfo.unit)) + ' this might look like this: "Volume = -2.49877 dB" + + + + + + Get some common information about an editable parameter to a class. + + The VST effect handle as returned by . + The index of the parameter (must be smaller than ). + An instance of the where to store the parameter information at. + If successful, is returned, else is returned. Use to get the error code. + + + + Get some common information about an editable parameter to a class. + + The VST effect handle as returned by . + The index of the parameter (must be smaller than ). + If successful, an instance of the is returned, else is returned. Use to get the error code. + + + + Returns the number of editable programs for the VST effect. + + The VST effect handle as returned by . + The number of available programs or 0 if no program is available. + Many (not all!) effects have more than one "program" that + can hold a complete set of parameters each. Moreover, some of these + programs may be initialized to some useful "factory defaults". + + + + + Returns the currently selected program for the VST effect. + + The VST effect handle as returned by . + The currect selected program number. Valid program numbers are between 0 and minus 1. + After construction (), always the first program (0) is selected. + With you can change the selected program. Functions as will always change the selected program's settings. + + + + + Sets (changes) the selected program for the VST effect. + + The VST effect handle as returned by . + The program number to set (between 0 and minus 1.). + If successful, is returned, else is returned. Use to get the error code. + You might call to check, if the VST effect has any editable programs available. + With you can check, which is the current selected program. Functions as as will always change the selected program's settings. + + + + + Returns a list parameter values of any program of a VST effect. + + + + + + + + Returns the parameters of a given program. + + The VST effect handle as returned by . + The program number for which to query the parameter values, must be smaller than . + An array of float values representing the parameter values of the given program or if the program (VST effect) has no parameters or an error occurred. + + The parameters of the currently selected program can also be queried by . + The function returns the parameters as an array of floats. The number of elements in the returned array is equal to . + If you set programIndex to -1, you can retrieve the effect's default values (these are the same values as returned by ). + This function does not change the selected program! + + + List all parameter values of a certain program: + + vstHandle = BassVst.BASS_VST_ChannelSetDSP(_stream, + "C:\\VstPlugins\\Ambience.dll", BASSVSTDsp.BASS_VST_DEFAULT, 1 ); + // get the number of available programs + int vstProgCount = BassVst.BASS_VST_GetProgramCount(vstHandle); + if (vstProgCount > 1) + { + // as an example get the parameters of program #1 (selected should be #0 in this case) + float[] progParams = BassVst.BASS_VST_GetProgramParam(vstHandle, 1); + if (progParams != null) + { + BASS_VST_PARAM_INFO paramInfo = new BASS_VST_PARAM_INFO(); + // loop over all paramter + for (int i=0; i<progParams.Length; i++) + { + // get the program's value + float paramValue = progParams[i]; + // qurey the info to get the parameter name + BassVst.BASS_VST_GetParamInfo(vstHandle, i, paramInfo); + + Console.WriteLine( String.Format( "{0} = {1}", paramInfo.name, paramValue ) ); + } + } + } + + + vstHandle = BassVst.BASS_VST_ChannelSetDSP(_stream, + "C:\VstPlugins\Ambience.dll", BASSVSTDsp.BASS_VST_DEFAULT, 1) + ' get the number of available programs + Dim vstProgCount As Integer = BassVst.BASS_VST_GetProgramCount(vstHandle) + If vstProgCount > 1 Then + ' as an example get the parameters of program #1 (selected should be #0 in this case) + Dim progParams As Single() = BassVst.BASS_VST_GetProgramParam(vstHandle, 1) + If Not (progParams Is Nothing) Then + Dim paramInfo As New BASS_VST_PARAM_INFO() + ' loop over all paramter + Dim i As Integer + For i = 0 To progParams.Length - 1 + ' get the program's value + Dim paramValue As Single = progParams(i) + ' qurey the info to get the parameter name + BassVst.BASS_VST_GetParamInfo(vstHandle, i, paramInfo) + + Console.WriteLine([String].Format("{0} = {1}", paramInfo.name, paramValue)) + Next i + End If + End If + + + + + + Set all parameters of any program in a VST effect. + + The VST effect handle as returned by . + The program number for which to set the parameter values, must be smaller than . + An array with the parameter values to set. The array needs to have as many elements as defined by or as returned be . + If successful, is returned, else is returned. Use to get the error code. + This function does not change the selected program! + If you use , the BASS_VST_PARAM_CHANGED event is only posted if you select a program with parameters different from the prior. + + + Copy all parameters from the current program to program #3: + + // get the current program number + int vstCurrProg = BassVst.BASS_VST_GetProgram(vstHandle); + // query all parameter values of the current program + float[] prog0Params = BassVst.BASS_VST_GetProgramParam(vstHandle, vstCurrProg); + // query all parameter values of the program #3 + float[] prog1aParams = BassVst.BASS_VST_GetProgramParam(vstHandle, 3); + // copy all parameters from the current program to #3 + bool ok = BassVst.BASS_VST_SetProgramParam(vstHandle, 3, prog0Params); + // and query all parameter values of the program #3 again... + float[] prog1bParams = BassVst.BASS_VST_GetProgramParam(vstHandle, 3); + + + ' get the current program number + Dim vstCurrProg As Integer = BassVst.BASS_VST_GetProgram(vstHandle) + ' query all parameter values of the current program + Dim prog0Params As Single() = BassVst.BASS_VST_GetProgramParam(vstHandle, vstCurrProg) + ' query all parameter values of the program #3 + Dim prog1aParams As Single() = BassVst.BASS_VST_GetProgramParam(vstHandle, 3) + ' copy all parameters from the current program to #3 + Dim ok As Boolean = BassVst.BASS_VST_SetProgramParam(vstHandle, 3, prog0Params) + ' and query all parameter values of the program #3 again... + Dim prog1bParams As Single() = BassVst.BASS_VST_GetProgramParam(vstHandle, 3) + + + + + + Gets the name of any program of a VST effect. + + The VST effect handle as returned by . + The program number for which to get the name, must be smaller than . + The name of the program given or if not valid. + The names are limited to 24 characters. This function does not change the selected program! + + + + Returns a list of all available program names. + + The VST effect handle as returned by . + An array of strings representing the list of available program names. The index corresponds to the program numbers. + You might use this method to enumerate over all programs or to initialize a menu for example. + This function does not change the selected program! + + + + + Sets the name of any program of a VST effect. + + The VST effect handle as returned by . + The program number for which to set the name, must be smaller than . + The new name to use. Names are limited to 24 characters, BASS_VST truncates the names, if needed. + If successful, is returned, else is returned. Use to get the error code. + This function does not change the selected program! + + + + Restores all default values for all VST effect parameters (on the current selected program). + + The VST effect handle as returned by . + Internally all default values for all parameters are retried . + + + // assign a Vst effect to a channel + int vst = BassVst.BASS_VST_ChannelSetDSP(_stream, + "C:\\VstPlugins\\Ambience.dll", BASSVSTDsp.BASS_VST_DEFAULT, 0); + + // change some parameters (e.g. #1 to 0.75) + BassVst.BASS_VST_SetParam(vst, 1, 0.75f); + + // restore all parameters to it's default values + BassVst.BASS_VST_SetParamRestoreDefaults(vst); + + + ' assign a Vst effect to a channel + Dim vst As Integer = BassVst.BASS_VST_ChannelSetDSP(_stream, + "C:\VstPlugins\Ambience.dll", BASSVSTDsp.BASS_VST_DEFAULT, 0) + + ' change some parameters (e.g. #1 to 0.75) + BassVst.BASS_VST_SetParam(vst, 1, 0.75F) + + ' restore all parameters to it's default values + BassVst.BASS_VST_SetParamRestoreDefaults(vst) + + + + + + Copies all parameters from one vstHandle to another one. + Both vstHandles must be of the same VST effect plugin! + + The source VST effect handle as returned by from where to copy the parameters. + The destination VST effect handle as returned by to where the parameters should be copied. + Copying parameters might be useful, if you created multiple instances of a VST effect plugin (e.g. for different channels). + + For crossfadings, you might use several BASS channels for playback - each should have the same VST-effects of course. + So changes done in the VST-editor need to be applied to several channels under some circumstances - on the other hand, if the player is stopped and no channel is available, the VST-editor should still be accessible. + + private VSTPROC _myVstProc; // make global, so GC will not collect it + private int vst1; + private int vst2; + private int ch1; + private int ch2; + ... + // create the 'real' channels to use + ch1 = BASS_StreamCreateFile(...); + vst1 = BassVst.BASS_VST_ChannelSetDSP(0, + "C:\\VstPlugins\\Ambience.dll", BASSVSTDsp.BASS_VST_DEFAULT, 1); + ch2 = BASS_StreamCreateFile(...); + vst2 = BassVst.BASS_VST_ChannelSetDSP(0, + "C:\\VstPlugins\\Ambience.dll", BASSVSTDsp.BASS_VST_DEFAULT, 1); + + // create an 'unchanneled' VST-editor + int vstDummy = BassVst.BASS_VST_ChannelSetDSP(0, + "C:\\VstPlugins\\Ambience.dll", BASSVSTDsp.BASS_VST_DEFAULT, 0); + + // we want to be notified about parameter changes ... + myVstProc = new VSTPROC(vstEditorCallback); + BassVst.BASS_VST_SetCallback(vstDummy, myVstProc, IntPtr.Zero); + + // so when the user opens the VST-editor this is being called + public int vstEditorCallback(int vstDummy, int action, int param1, int param2, IntPtr user) + { + if (action == BASS_VST_PARAM_CHANGED) + { + // the user has changed some slider in the unchanneled editor + // copy the changes to the 'real' channels + BassVst.BASS_VST_SetParamCopyParams(vstDummy, vst1); + BassVst.BASS_VST_SetParamCopyParams(vstDummy, vst2); + } + return 0; + } + + + Private _myVstProc As VSTPROC ' make global, so GC will not collect it + Private vst1 As Integer + Private vst2 As Integer + Private ch1 As Integer + Private ch2 As Integer + ... + ' create the 'real' channels to use + ch1 = BASS_StreamCreateFile(...) + vst1 = BassVst.BASS_VST_ChannelSetDSP(0, + "C:\VstPlugins\Ambience.dll", BASSVSTDsp.BASS_VST_DEFAULT, 1) + ch2 = BASS_StreamCreateFile(...) + vst2 = BassVst.BASS_VST_ChannelSetDSP(0, + "C:\VstPlugins\Ambience.dll", BASSVSTDsp.BASS_VST_DEFAULT, 1) + + ' create an 'unchanneled' VST-editor + Dim vstDummy As Integer = BassVst.BASS_VST_ChannelSetDSP(0, + "C:\VstPlugins\Ambience.dll", BASSVSTDsp.BASS_VST_DEFAULT, 0) + + ' we want to be notified about parameter changes ... + myVstProc = New VSTPROC(vstEditorCallback) + BassVst.BASS_VST_SetCallback(vstDummy, myVstProc, IntPtr.Zero) + + ' so when the user opens the VST-editor this is being called + Public Function vstEditorCallback(vstDummy As Integer, action As Integer, + param1 As Integer, param2 As Integer, user As IntPtr) As Integer + If action = BASS_VST_PARAM_CHANGED Then + ' the user has changed some slider in the unchanneled editor + ' copy the changes to the 'real' channels + BassVst.BASS_VST_SetParamCopyParams(vstDummy, vst1) + BassVst.BASS_VST_SetParamCopyParams(vstDummy, vst2) + End If + Return 0 + End Function + + + + + + Call this function after position changes or sth. like that. + + The VST effect handle as returned by . + If successful, is returned, else is returned. Use to get the error code. + Some VST effects will use an internal buffer for effect calculation and handling. + This will reset the internal VST buffers which may remember some "old" data. + + + + + Bypasses the effect processing (state=) or switch back to normal processing (state=). + + The VST effect handle as returned by . + to bypasses the effect processing; to switch back to normal processing. + If successful, is returned, else is returned. Use to get the error code. + By default bypassing is OFF and the effect will be processed normally. Use returns the current state. + Note, that the bypassing is completely done by BASS_VST, we're not using the so-called "soft" bypass that is implemented by some effects. + This is for the following reasons: + - Soft-bypassing is not supported by all effects + - The state of soft-bypassing cannot be queried safely + - Soft-bypassing would not be a real bypass as some channel transformations may still be needed + - Performance reasons - soft-bypassing would require still most of the needed BASS_VST transformations + - Finally, I do not see any advantages of the soft-bypassing + Soft bypassing is not supported in the BASS.NET API. + + + + + Gets the current bypasses state of the the effect processing (state= or ). + + The VST effect handle as returned by . + If successful, is returned, else is returned. Use to get the error code. + + + + Gets general information about a VST effect plugin. + + The VST effect handle as returned by . + An instance of the where to store the parameter information at. + If successful, is returned, else is returned. Use to get the error code. + Some words to the number of input/output channels: + VST effects that have no input channels (so called "Instruments") are not loaded by BASS_VST. So you can assume chansIn and chansOut to be at least 1. + Multi-channel streams should work correctly, if supported by a effect. + If not, only the first chansIn channels are processed by the effect, the other ones stay unaffected. + The opposite, eg. assigning multi-channel effects to stereo channels, should be no problem at all. + If mono effects are assigned to stereo channels, the result will be mono, expanded to both channels. + This behaviour can be switched of using the BASS_VST_KEEP_CHANS in . + + + + BASS_VST_INFO vstInfo = new BASS_VST_INFO(); + if ( BassVst.BASS_VST_GetInfo(vstHandle, vstInfo)) + Console.WriteLine(vstInfo.ToString()); + + + Dim vstInfo As New BASS_VST_INFO() + If BassVst.BASS_VST_GetInfo(vstHandle, vstInfo) Then + Console.WriteLine(vstInfo.ToString()) + End If + + + + + + Gets general information about a VST effect plugin. + + The VST effect handle as returned by . + If successful, an instance of the is returned, else is returned. Use to get the error code. + Some words to the number of input/output channels: + VST effects that have no input channels (so called "Instruments") are not loaded by BASS_VST. So you can assume chansIn and chansOut to be at least 1. + Multi-channel streams should work correctly, if supported by a effect. + If not, only the first chansIn channels are processed by the effect, the other ones stay unaffected. + The opposite, eg. assigning multi-channel effects to stereo channels, should be no problem at all. + If mono effects are assigned to stereo channels, the result will be mono, expanded to both channels. + This behaviour can be switched of using the BASS_VST_KEEP_CHANS in . + + + + BASS_VST_INFO vstInfo = BassVst.BASS_VST_GetInfo(vstHandle); + if (vstInfo != null) + Console.WriteLine(vstInfo.ToString()); + + + Dim vstInfo As BASS_VST_INFO = BassVst.BASS_VST_GetInfo(vstHandle) + If Not (vstInfo Is Nothing) Then + Console.WriteLine(vstInfo.ToString()) + End If + + + + + + Many VST effects come along with an graphical parameters editor; with the following function, you can embed these editors to your user interface. + + The VST effect handle as returned by . + The IntPtr to the window handle (HWND) of the parents window in which the editor should be embedded (e.g. use a new modeless dialog or user control). + If successful, is returned, else is returned. Use to get the error code. + + To embed the editor to another window, call this function with parentWindow set to the HWND (this.Handle) of the parent window. + To check, if an effect has an editor, see the hasEditor flag set by . + To "unembed" the editor, call this function with parentWindow set to . + If you create the editor window independently of a real channel (by skipping the channel parameter when calling ) and the editor displays any spectrums, VU-meters or such, + the data for this come from the most recent channel using the same effect and the same scope. + The scope can be set by to any ID, the default is 0. + In order to create a new window in which the editor should be embedded, it is a good idea to call in order to retrieve the editors height and width. + + + + private int _vstHandle = 0; + ... + _vstHandle = BassVst.BASS_VST_ChannelSetDSP(_stream, + "C:\\VstPlugins\\Ambience.dll", BASSVSTDsp.BASS_VST_DEFAULT, 1 ); + // show the embedded editor + BASS_VST_INFO vstInfo = new BASS_VST_INFO(); + if ( BassVst.BASS_VST_GetInfo(vstHandle, vstInfo) && vstInfo.hasEditor ) + { + // create a new System.Windows.Forms.Form + Form f = new Form(); + f.Width = vstInfo.editorWidth+4; + f.Height = vstInfo.editorHeight+34; + f.Closing += new CancelEventHandler(f_Closing); + f.Text = vstInfo.effectName; + f.Show(); + BassVst.BASS_VST_EmbedEditor(_vstHandle, f.Handle); + } + + private void f_Closing(object sender, CancelEventArgs e) + { + // unembed the VST editor + BassVst.BASS_VST_EmbedEditor(_vstHandle, IntPtr.Zero); + } + + + Private _vstHandle As Integer = 0 + ... + _vstHandle = BassVst.BASS_VST_ChannelSetDSP(_stream, + "C:\VstPlugins\Ambience.dll", BASSVSTDsp.BASS_VST_DEFAULT, 1) + ' show the embedded editor + Dim vstInfo As New BASS_VST_INFO() + If BassVst.BASS_VST_GetInfo(vstHandle, vstInfo) AndAlso vstInfo.hasEditor Then + ' create a new System.Windows.Forms.Form + Dim f As New Form() + f.Width = vstInfo.editorWidth + 4 + f.Height = vstInfo.editorHeight + 34 + AddHandler f.Closing, AddressOf f_Closing + f.Text = vstInfo.effectName + f.Show() + BassVst.BASS_VST_EmbedEditor(_vstHandle, f.Handle) + End If + + Private Sub f_Closing(sender As Object, e As CancelEventArgs) + ' unembed the VST editor + BassVst.BASS_VST_EmbedEditor(_vstHandle, IntPtr.Zero) + End Sub + + + + + + Sets the scope of an Editor to a given ID. + + The VST effect handle as returned by . + The ID to set the scope to. + If successful, is returned, else is returned. Use to get the error code. + + If you create an editor window with independently of a real channel (by skipping the channel parameter when calling ) + and the editor displays any spectrums, VU-meters or such, the data for this come from the most recent channel using the same effect + and the same scope. The scope can be set by this method to any ID, the default is 0. + The 'scope' is used to forward 'real' audio data to 'unchanneled' editors (you may want to use these editors as you may want the user to open the editor window at any time, independent of a playing channel). + Imaging the following code, where two streams are prepared for crossfading: + + ch1 = BASS_StreamCreateFile(false, "sth1.mp3", ...); + dsp1 = BASS_VST_ChannelSetDSP(ch1, "sth.dll", ...); + ch2 = BASS_StreamCreateFile(false, "sth2.mp3", ...); + dsp2 = BASS_VST_ChannelSetDSP(ch2, "sth.dll", ...); + + For the user, this is one logical channel. If the user opens the editor for the 'sth' effect, it should display first the spectrum/vu/etc. from the first, + after crossfading from the second channel. To let the editor know this, you should use the 'scope'. + The 'scope' simply brings independent channels together to one logical unit - mainly for displaying the correct spectrum/vu/etc. in the editors. + + So before the crossfade, you should set the scope: + + BASS_VST_SetScope(dsp1, 123); // any number, scope is created implicitly + BASS_VST_SetScope(dsp2, 123); // any number, scope is created implicitly + + + To open the unchanneled editor, you can then simply use the following code: + + editor = BASS_VST_ChannelSetDSP(0, "sth.dll", ...); + BASS_VST_SetScope(editor, 123); + BASS_VST_EmbedEditor(editor, ...); + + The editor can then be opened, closed, created and destroyed independingly of the playing stuff. + + If you use BASSmix, maybe you won't need the VST-scopes as you can add the effects to the finaly mix. However, even in this case, there may be situations where is just fine and simplifies your code. + + + + + + + + Assign a callback function to a vstHandle. + + The VST effect handle as returned by . + The user defined callback delegate (see ). + User instance data to pass to the callback function. + If successful, is returned, else is returned. Use to get the error code. + + The callback function is called with one of the following actions (see ): + + Actions: + BASS_VST_PARAM_CHANGEDSome parameters are changed by the editor opened by , NOT called if you call . + BASS_VST_EDITOR_RESIZEDThe embedded editor window should be resized, the new width/height can be found in param1/param2 and in . + BASS_VST_AUDIO_MASTERCan be used to subclass the audioMaster callback (see the VST SDK), param1 is a pointer to a structure. + + + Unless defined otherwise, the callback function should always return 0. + + + + private VSTPROC _myVstProc; // keep the callback delegate in a global member + ... + // your VST callback - referenced below by BASS_VST_SetCallback() + private int YourVstProc(int vstHandle, BASSVSTAction action, int param1, int param2, IntPtr user) + { + switch (action) + { + case BASSVSTAction.BASS_VST_PARAM_CHANGED: + // we get notified that the user has changed some sliders in the editor - + // do what to do here ... + break; + case BASSVSTAction.BASS_VST_EDITOR_RESIZED: + // the editor window requests a new size, + // maybe we should resize the window the editor is embedded in? + // the new width/height can be found in param1/param2 + break; + case BASSVSTAction.BASS_VST_AUDIO_MASTER: + // this is only for people familiar with the VST SDK, + // param1 is a pointer to a BASS_VST_AUDIO_MASTER_PARAM structure + // which contains all information needed + break; + } + return 0; + } + ... + // open the VST editor (e.g. if we are inside a System.Windows.Forms.Form) + BassVst.BASS_VST_EmbedEditor(vstHandle, this.Handle); + // we want to get notified for parameter changes etc. + _myVstProc = new VSTPROC(YourVstProc); + BassVst.BASS_VST_SetCallback(vstHandle, _myVstProc, IntPtr.Zero); + + + Private _myVstProc As VSTPROC ' keep the callback delegate in a global member + ... + ' your VST callback - referenced below by BASS_VST_SetCallback() + Private Function YourVstProc(vstHandle As Integer, action As BASSVSTAction, param1 As Integer, param2 As Integer, user As IntPtr) As Integer + Select Case action + Case BASSVSTAction.BASS_VST_PARAM_CHANGED + ' we get notified that the user has changed some sliders in the editor - + ' do what to do here ... + Case BASSVSTAction.BASS_VST_EDITOR_RESIZED + ' the editor window requests a new size, + ' maybe we should resize the window the editor is embedded in? + ' the new width/height can be found in param1/param2 + Case BASSVSTAction.BASS_VST_AUDIO_MASTER + ' this is only for people familiar with the VST SDK, + ' param1 is a pointer to a BASS_VST_AUDIO_MASTER_PARAM structure + ' which contains all information needed + End Select + Return 0 + End Function + ... + ' open the VST editor (e.g. if we are inside a System.Windows.Forms.Form) + BassVst.BASS_VST_EmbedEditor(vstHandle, Me.Handle) + ' we want to get notified for parameter changes etc. + _myVstProc = New VSTPROC(AddressOf YourVstProc) + BassVst.BASS_VST_SetCallback(vstHandle, _myVstProc, IntPtr.Zero) + + + + + + Set the VST language to be used by any plugins. + + The desired language as ISO 639.1, e.g. "en", "de", "es"... + If successful, is returned, else is returned. Use to get the error code. + + Some VST effects come along localized. With this function you can set the + desired language as ISO 639.1 -- eg. "en" for english, "de" for german, + "es" for spanish and so on. The default language is english. + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + Load BASS and BASSVST from the application's startup path: + + Bass.LoadMe(); + BassVst.LoadMe(); + ... + // when not used anymore... + BassVst.FreeMe(); + Bass.FreeMe(); + + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + Load BASS and BASSVST from a different directory: + + Bass.LoadMe( @"C:\Development\BASS\_libs" ); + BassVst.LoadMe( @"C:\Development\BASS\_libs" ); + ... + // when not used anymore... + BassVst.FreeMe(); + Bass.FreeMe(); + + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + VST DSP flags to be used within the method. + + + + + Default VST DSP processing. + + + + + By default, mono effects assigned to stereo channels are mixed down before processing and converted back + to stereo afterwards. Set this flag to avoid this behaviour in which case only the first channel is + affected by processing. + + + + + File is a Unicode (16-bit characters) filename. + + + + + VST action parameters as used within the callback. + See also . + + + + + Some parameters are changed by the editor opened by , NOT called if you call . + + + + + The embedded editor window should be resized, the new width/height can be found in param1/param2 and in . + + + + + Can be used to subclass the audioMaster callback (see the VST SDK), param1 is a pointer to a instance of the class. + + + + + VST Dispatcher OpCodes to be used within the callback when using . + For more info see the Steinberg VST SDK documentation. + + + + + Initialise. + + + + + Exit, release all memory and other resources! + + + + + Program number in "value". + + + + + Returns the current program number. + + + + + User changed program name (max 24 char + 0) to as passed in string. + + + + + Stuff program name (max 24 char + 0) into string. + + + + + Stuff parameter "index" label (max 8 char + 0) into string. + Examples: 'sec', 'dB', 'type' + + + + + Stuff parameter "index" textual representation into string. + Examples: '0.5', '-3', 'PLATE' + + + + + Stuff parameter "index" label (max 8 char + 0) into string. + Examples: 'Time', 'Gain', 'RoomType' + + + + + Called if (flags & (effFlagsHasClip | effFlagsHasVu)). + + + + + System: In opt (float value in Hz; for example 44100.0Hz). + + + + + System: In value (this is the maximun size of an audio block, pls check sampleframes in process call). + + + + + System: The user has switched the 'power on' button to value (0 off, else on). This only switches audio processing; you should flush delay buffers etc. + + + + + Editor: Stuff rect (top, left, bottom, right) into ptr. + + + + + Editor: System dependant Window pointer in ptr. + + + + + Editor: No arguments. + + + + + Editor: Draw method, ptr points to rect (MAC Only). + + + + + Editor: index: x, value: y (MAC Only). + + + + + Editor: System keycode in value. + + + + + Editor: no arguments. Be gentle! + + + + + Editor: Window has topped, no arguments. + + + + + Editor: Window goes to background. + + + + + Returns 'NvEf'. + + + + + Host requests pointer to chunk into (void**)ptr, byteSize returned. + + + + + Plug-in receives saved chunk, byteSize passed. + + + + + VstEvents* in "ptr". + + + + + Parameter index in "index". + + + + + Parameter index in "index", string in "ptr". + + + + + No arguments. This is for dividing programs into groups (like GM). + + + + + Get program name of category "value", program "index" into "ptr". + Category (that is, "value") may be -1, in which case program indices are enumerated linearily (as usual); otherwise, each category starts over with index 0. + + + + + Copy current program to destination "index" + Note: implies setParameter connections, configuration. + + + + + Input at "index" has been (dis-)connected; "value" == 0: disconnected, else connected. + + + + + Onput at "index" has been (dis-)connected; "value" == 0: disconnected, else connected. + + + + + "index", VstPinProperties* in ptr, return != 0 means true. + + + + + "index", VstPinProperties* in ptr, return != 0 means true. + + + + + No parameter, return value is category. + + + + + Realtime: for external dsp, see flag bits below. + + + + + Realtime: for external dsp, see flag bits below. returns float*. + + + + + Offline: ptr = VstAudioFile array, value = count, index = start flag. + + + + + Offline: ptr = VstOfflineTask array, value = count. + + + + + Offline: ptr = VstOfflineTask array, value = count. + + + + + VstVariableIo* in "ptr". + + + + + VstSpeakerArrangement* pluginInput in "value"; VstSpeakerArrangement* pluginOutput in "ptr". + + + + + Block size in "value", sampleRate in "opt" + + + + + On/Off in "value" (0 = off, 1 = on). + + + + + char* name (max 32 bytes) in "ptr". + + + + + char* text (max 256 bytes) in "ptr". + + + + + Fills "ptr" with a string identifying the vendor (max 64 char). + + + + + Fills "ptr" with a string with product name (max 64 char). + + + + + Returns vendor-specific version. + + + + + No definition, vendor specific handling. + + + + + "ptr" contains one of the 'plugCanDos' strings (e.g. "bypass"). + + + + + Returns tail size; 0 is default (return 1 for 'no tail'). + + + + + Idle call in response to audioMasterneedIdle. Must return 1 to keep idle calls beeing issued. + + + + + GUI: void* in "ptr", not yet defined. + + + + + GUI: set view position (in window) to x "index" y "value" + + + + + Of param "index", VstParameterProperties* in "ptr". + + + + + Returns 0: needs keys (default for 1.0 plugs), 1: don't need. + + + + + Returns 2 for VST 2; older versions return 0; 2100 for VST 2.1...2400 for VST 2.4. + + + + + Character in "index", virtual in "value", modifiers in "opt", return -1 if not used, return 1 if used. + + + + + Character in "index", virtual in "value", modifiers in "opt", return -1 if not used, return 1 if used. + + + + + Mode in "value": 0: circular, 1:circular relativ, 2:linear. + + + + + Passed "ptr" points to MidiProgramName struct. + Struct will be filled with information for 'thisProgramIndex'. + Returns number of used programIndexes, if 0 is returned, no MidiProgramNames supported. + + + + + Returns the programIndex of the current program. + Passed "ptr" points to MidiProgramName struct, struct will be filled with information for the current program. + + + + + Passed "ptr" points to MidiProgramCategory struct. + Struct will be filled with information for 'thisCategoryIndex'. + Returns number of used categoryIndexes, if 0 is returned, no MidiProgramCategories supported. + + + + + Returns 1 if the MidiProgramNames or MidiKeyNames had changed on this channel, 0 otherwise. "ptr" ignored. + + + + + Passed "ptr" points to MidiKeyName struct. + Struct will be filled with information for 'thisProgramIndex' and 'thisKeyNumber'. + If keyName is "" the standard name of the key will be displayed. If 0 is returned, no MidiKeyNames are defined for 'thisProgramIndex'. + + + + + + Called before a new program is loaded. + + + + + Called when the program is loaded. + + + + + VstSpeakerArrangement** pluginInput in "value". VstSpeakerArrangement** pluginOutput in "ptr". + + + + + This opcode is only called, if plugin is of type kPlugCategShell. Returns the next plugin's uniqueID. + "ptr" points to a char buffer of size 64, which is to be filled with the name of the plugin including the terminating zero. + + + + + Called before the start of process call. + + + + + Called after the stop of process call. + + + + + Called in offline (non RealTime) Process before process is called, indicates how many sample will be processed. + + + + + PanLaw : Type (Linear, Equal Power,.. see enum PanLaw Type) in "value", Gain in "opt": for Linear : [1.0 means 0dB PanLaw], [~0.58 means -4.5dB], [0.5 means -6.02dB]. + + + + + Called before a Bank is loaded, "ptr" points to VstPatchChunkInfo structure. + Return -1 if the Bank can not be loaded, return 1 if it can be loaded else 0 (for compatibility). + + + + + Called before a Program is loaded, "ptr" points to VstPatchChunkInfo structure. + Return -1 if the Program can not be loaded, return 1 if it can be loaded else 0 (for compatibility). + + + + + Sets the processing precision in "value" (0=32 bit, 1=64 bit). + + + + + Returns the number of used MIDI input channels (1-15). + + + + + Returns the number of used MIDI output channels (1-15). + + + + + Returns the number of available OpCodes + + + + + bit flags. + + + + + If set, is expected to react to editor messages. + + + + + Return > 1. in getVu() if clipped. + + + + + Return vu value in getVu(); > 1. means clipped. + + + + + If numInputs == 2, makes sense to be used for mono in. + + + + + Supports in place output (processReplacing() exsists). + + + + + Program data are handled in formatless chunks. + + + + + Plug-in is a synth (VSTi), Host may assign mixer channels for its outputs. + + + + + Plug-in does not produce sound when input is all silence. + + + + + Plug-in is asynchronious. + + + + + Plug-in has a buffer. + + + + + Plug-in supports double precision processing. + + + + + Common information structure about an editable parameter to a VST plugin parameter to be used with . + + + + + Name of the parameter (empty strings returned if a plugin does not provide these information). + Examples: Time, Gain, RoomType + + + + + Unit of the parameter. + Examples: sec, dB, type + + + + + The current value in a readable format (empty strings returned if a plugin does not provide these information). + Examples: 0.5, -3, PLATE + + + + + The default value (in the range of 0.0 and 1.0). + + + + + Default constructor. + + + + + A description of the VST parameter value (name = display unit, e.g. Gain = 0.7 dB). + + A description of the VST parameter value (name = display unit, e.g. Gain = 0.7 dB). + + + + writes some information about a vstHandle returned by to this BASS_VST_INFO structure. + + Some words to the number of input/output channels: + VST effects that have no input channels (so called "Instruments") are not loaded by BASS_VST. So you can assume chansIn and chansOut to be at least 1. + Multi-channel streams should work correctly, if supported by a effect. + If not, only the first chansIn channels are processed by the effect, the other ones stay unaffected. + The opposite, eg. assigning multi-channel effects to stereo channels, should be no problem at all. + If mono effects are assigned to stereo channels, the result will be mono, expanded to both channels. + This behaviour can be switched of using the BASS_VST_KEEP_CHANS in . + + + + + The channelHandle as given to . + + + + + A unique ID for the effect (the IDs are registered at Steinberg). + + + + + The effect name (empty strings returned if a plugin does not provide these information). + + + + + The effect version (example 0x01010000 for version 1.1.0.0). + + + + + The VST version, the effect was written for (example 0x02030000 for version 2.3.0.0). + + + + + The VST version supported by BASS_VST (e.g. 2.4). + + + + + The product name (may be empty). + + + + + The vendor name (may be empty). + + + + + The vendor-specific version number (example 0x01010000 for version 1.1.0.0). + + + + + Maximum number of possible input channels (should be at least 1 here). + + + + + Maximum number of possible output channels (should be at least 1 here). + + + + + For algorithms which need input in the first place, in number of samples. + + + + + Has this plugin an embedded editor? + If , the method can be called. + + + + + Initial/current width of the embedded editor, see also BASS_VST_EDITOR_RESIZED in . + For a very few plugins, editorWidth and editorHeight may be 0 if the editor is not yet opened. + + + + + Initial/current height of the embedded editor, see also BASS_VST_EDITOR_RESIZED in . + For a very few plugins, editorWidth and editorHeight may be 0 if the editor is not yet opened. + + + + + The underlying AEffect object (see the VST SDK). + + + + + =the VST plugin is an instrument, =the VST plugin is an effect. + + + + + The internal DSP handle. + + + + + Default constructor. + + + + + Returns a description string for the VST plugin info. + + Returns a description string for the VST plugin info (effectName, productName, vendorName). + + + + This class is only needed if you subclass the audioMaster callback using BASS_VST_AUDIO_MASTER in the (see the VST DSK for more information). + + + + + Parameter forwarded from the audioMaster callback. + + + + + Parameter forwarded from the audioMaster callback (one of the ). + + + + + Parameter forwarded from the audioMaster callback. + + + + + Parameter forwarded from the audioMaster callback. + + + + + Parameter forwarded from the audioMaster callback. + + + + + Parameter forwarded from the audioMaster callback. + + + + + Set this to 0 if you want to skip the normal BASS_VST audioMaster processing. + In this case the return value is forwarded to the effect. + + + + + Default Constructor. + + + + + Basic VST Effect class as returned in the aeffect member of the class as obtained by . + See the VST SDK for more informaton. + + This class can only be used in the .Net Framework version 2.0 or above! + In order to retrieve an instance of this class you must first call and then pass the IntPtr to the + static method . + + + + + Must be kEffectMagic ('VstP') + + + + + Host to Plug-in dispatcher delegate method (see ). + + + + + Accumulating process mode delegate method (deprecated in VST 2.4, use processReplacing instead - see ). + + + + + Set new value of automatable parameter (see ). + + + + + Returns current value of automatable parameter (see ). + + + + + Number of programs. + + + + + All programs are assumed to have numParams parameters. + + + + + Number of audio inputs. + + + + + Number of audio outputs. + + + + + Effect flags (see ). + + + + + Reserved for Host, must be 0. + + + + + Reserved for Host, must be 0. + + + + + For algorithms which need input in the first place (group delay or latency). This value should be initialized in a resume state. + + + + + Number of realtime qualities (0: realtime). + Deprecated in VST 2.4! + + + + + Number of offline qualities (0: realtime only). + Deprecated in VST 2.4! + + + + + Input samplerate to output samplerate ratio, not used yet. + Deprecated in VST 2.4! + + + + + AudioEffect class pointer. + + + + + User-defined pointer. + + + + + Registered unique identifier (register it at Steinberg 3rd party support Web). This is used to identify a plug-in during save+load of preset and project. + + + + + Plug-in version (example 0x1100 for version 1.1.0.0) + + + + + Realtime process mode delegate method (see ). + + + + + Process double-precision audio samples in replacing mode (see ). + + + + + Reserved for future use (please zero) + + + + + Default constructor. + + + + + Returns an instance of the class derived from an IntPtr (aeffect) as obtained via . + + The IntPtr to the AEffect structure as obtained from the class when calling . + An instance of the class if successfull, otherwise will be returned. + This method can only be used in the .Net Framework version 2.0 or above! + + + vstHandle = BassVst.BASS_VST_ChannelSetDSP(_stream, + "C:\\VstPlugins\\Ambience.dll", BASSVSTDsp.BASS_VST_DEFAULT, 0); + BASS_VST_INFO vstInfo = new BASS_VST_INFO(); + if (BassVst.BASS_VST_GetInfo(vstHandle, vstInfo)) + { + BASS_VST_AEFFECT aeffect = BASS_VST_AEFFECT.FromIntPtr(vstInfo.aeffect); + if (aeffect != null) + { + // now you might use the aeffect instance, e.g. retrieve the number of programs... + int numPrograms = aeffect.numPrograms; + ... + // or call the dispatcher... + string cmd = "bypass"; + GCHandle gch = GCHandle.Alloc(cmd, GCHandleType.Pinned); + if (aeffect.dispatcher(vstInfo.aeffect, BASSVSTDispatcherOpCodes.effCanDo, + 0, 0, gch.AddrOfPinnedObject(), 0.0f) != 0) + { + int ret = aeffect.dispatcher(vstInfo.aeffect, BASSVSTDispatcherOpCodes.effSetBypass, + 0, 1, IntPtr.Zero, 0.0f); + Console.WriteLine(ret.ToString()); + } + gch.Free(); + ... + } + } + + + vstHandle = BassVst.BASS_VST_ChannelSetDSP(_stream, + "C:\VstPlugins\Ambience.dll", BASSVSTDsp.BASS_VST_DEFAULT, 0) + Dim vstInfo As New BASS_VST_INFO() + If BassVst.BASS_VST_GetInfo(vstHandle, vstInfo) Then + Dim aeffect As BASS_VST_AEFFECT = BASS_VST_AEFFECT.FromIntPtr(vstInfo.aeffect) + If Not (aeffect Is Nothing) Then + ' now you might use the aeffect instance, e.g. retrieve the number of programs + Dim numPrograms As Integer = aeffect.numPrograms + ... + ' or call the dispatcher... + Dim cmd As String = "bypass" + Dim gch As GCHandle = GCHandle.Alloc(cmd, GCHandleType.Pinned) + If aeffect.dispatcher(vstInfo.aeffect, BASSVSTDispatcherOpCodes.effCanDo, + 0, 0, gch.AddrOfPinnedObject(), 0F) <> 0 Then + Dim ret As Integer = aeffect.dispatcher(vstInfo.aeffect, BASSVSTDispatcherOpCodes.effSetBypass, + 0, 1, IntPtr.Zero, 0F) + ... + Console.WriteLine(ret.ToString()) + End If + gch.Free() + ... + End If + End If + + + + + + Returns the description of this instance (In=x, Out=y). + + Returns the description of this instance (In=x, Out=y). + + + + Returns the currently selected program name of the VST effect. + + The name of the selected program - or an empty string, if the effect has no programs. + + + + Returns a specific program name of the VST effect. + + The number of the program to return (must be between 0 .. numPrograms-1). + The name of the selected program - or an empty string, if the effect has no programs. + Retrieving a program name other than the current one enforces to change the current program inernally. + So this method first retrieves the current program number, then changes the program in order to get that name and afterwards restores the currect selected program. + But since changing the program is enforced even for a short period of time, calling this method on a channel based VST effect might produce some sound disturbance. + So it is a good idea to either call this method on a non-channel vstHandle ( called with chan=0) or make sure the channel is currently not playing. + + + Calling on a non-channel vstHandle: + + vstHandle = BassVst.BASS_VST_ChannelSetDSP(0, + "C:\\VstPlugins\\Ambience.dll", BASSVSTDsp.BASS_VST_DEFAULT, 0); + BASS_VST_INFO vstInfo = new BASS_VST_INFO(); + if ( BassVst.BASS_VST_GetInfo(vstHandle, vstInfo) ) + { + if (vstInfo.aeffect != IntPtr.Zero) + { + BASS_VST_AEFFECT aeffect = BASS_VST_AEFFECT.FromIntPtr(vstInfo.aeffect); + // list all available programs + for (int i=0; i<aeffect.numPrograms; i++) + Console.WriteLine( aeffect.GetProgramName(i) ); + } + } + + + vstHandle = BassVst.BASS_VST_ChannelSetDSP(0, "C:\VstPlugins\Ambience.dll", BASSVSTDsp.BASS_VST_DEFAULT, 0) + Dim vstInfo As New BASS_VST_INFO() + If BassVst.BASS_VST_GetInfo(vstHandle, vstInfo) Then + If vstInfo.aeffect <> IntPtr.Zero Then + Dim aeffect As BASS_VST_AEFFECT = BASS_VST_AEFFECT.FromIntPtr(vstInfo.aeffect) + ' list all available programs + Dim i As Integer + For i = 0 To aeffect.numPrograms - 1 + Console.WriteLine(aeffect.GetProgramName(i)) + Next i + End If + End If + + + + + + Returns an array of strings representing the available program names. + + An array of strings representing the available program names. + Retrieving a program name other than the current one enforces to change the current program inernally. + So this method first retrieves the current program number, then changes the program in order to get that name and afterwards restores the currect selected program. + But since changing the program is enforced even for a short period of time, calling this method on a channel based VST effect might produce some sound disturbance. + So it is a good idea to either call this method on a non-channel vstHandle ( called with chan=0) or make sure the channel is currently not playing. + + + Calling on a non-channel vstHandle: + + vstHandle = BassVst.BASS_VST_ChannelSetDSP(0, + "C:\\VstPlugins\\Ambience.dll", BASSVSTDsp.BASS_VST_DEFAULT, 0); + BASS_VST_INFO vstInfo = new BASS_VST_INFO(); + if (BassVst.BASS_VST_GetInfo(vstHandle, vstInfo)) + { + if (vstInfo.aeffect != IntPtr.Zero) + { + // get all available programs + string[] progs = aeffect.GetProgramNames(); + if (progs != null) + { + for (int i = 0; i < progs.Length; i++) + Console.WriteLine(String.Format( "{0}: {1}", i, progs[i])); + } + } + } + + + vstHandle = BassVst.BASS_VST_ChannelSetDSP(0, + "C:\VstPlugins\Ambience.dll", BASSVSTDsp.BASS_VST_DEFAULT, 0) + Dim vstInfo As New BASS_VST_INFO() + If BassVst.BASS_VST_GetInfo(vstHandle, vstInfo) Then + If vstInfo.aeffect <> IntPtr.Zero Then + ' get all available programs + Dim progs As String() = aeffect.GetProgramNames() + If Not (progs Is Nothing) Then + Dim i As Integer + For i = 0 To progs.Length - 1 + Console.WriteLine([String].Format("{0}: {1}", i, progs(i))) + Next i + End If + End If + End If + + + + + + Returns the currently selected program number of the VST effect. + + The name of the selected program - or an empty string, if the effect has no programs. + + + + Sets the selected program number of the VST effect. + + The number of the program to set (must be between 0 .. numPrograms-1). + on success, else . + + + + Sets (overwrites) the current selected program name of the VST effect. + + The new name of the program to set (max. 24 characters long!). + on success, else . + This changes only the name to the VST effect program name, but does not change the program istself. + + + + + User defined VST callback method to be used with . + + The VST plugin handle as returned from . + The action parameter, one of the values (see below). + The first parameter (see the VST SDK for further details). + The second parameter (see the VST SDK for further details). + The user parameter as specified in the call. + Unless defined otherwise, the callback function should always return 0. + + The callback function is called with one of the following actions (see ): + + Actions: + BASS_VST_PARAM_CHANGEDSome parameters are changed by the editor opened by , NOT called if you call . + BASS_VST_EDITOR_RESIZEDThe embedded editor window should be resized, the new width/height can be found in param1/param2 and in . + BASS_VST_AUDIO_MASTERCan be used to subclass the audioMaster callback (see the VST SDK), param1 is a pointer to a structure. + + + + + + private VSTPROC _myVstProc; // keep the callback delegate in a global member + ... + // your VST callback - referenced below by BASS_VST_SetCallback() + private int YourVstProc(int vstHandle, BASSVSTAction action, int param1, int param2, IntPtr user) + { + switch (action) + { + case BASSVSTAction.BASS_VST_PARAM_CHANGED: + // we get notified that the user has changed some sliders in the editor - + // do what to do here ... + break; + case BASSVSTAction.BASS_VST_EDITOR_RESIZED: + // the editor window requests a new size, + // maybe we should resize the window the editor is embedded in? + // the new width/height can be found in param1/param2 + break; + case BASSVSTAction.BASS_VST_AUDIO_MASTER: + // this is only for people familiar with the VST SDK, + // param1 is a pointer to a BASS_VST_AUDIO_MASTER_PARAM structure + // which contains all information needed + break; + } + return 0; + } + ... + // open the VST editor (e.g. if we are inside a System.Windows.Forms.Form) + BassVst.BASS_VST_EmbedEditor(vstHandle, this.Handle); + // we want to get notified for parameter changes etc. + _myVstProc = new VSTPROC(YourVstProc); + BassVst.BASS_VST_SetCallback(vstHandle, _myVstProc, IntPtr.Zero); + + + Private _myVstProc As VSTPROC ' keep the callback delegate in a global member + ... + ' your VST callback - referenced below by BASS_VST_SetCallback() + Private Function YourVstProc(vstHandle As Integer, action As BASSVSTAction, param1 As Integer, param2 As Integer, user As IntPtr) As Integer + Select Case action + Case BASSVSTAction.BASS_VST_PARAM_CHANGED + ' we get notified that the user has changed some sliders in the editor - + ' do what to do here ... + Case BASSVSTAction.BASS_VST_EDITOR_RESIZED + ' the editor window requests a new size, + ' maybe we should resize the window the editor is embedded in? + ' the new width/height can be found in param1/param2 + Case BASSVSTAction.BASS_VST_AUDIO_MASTER + ' this is only for people familiar with the VST SDK, + ' param1 is a pointer to a BASS_VST_AUDIO_MASTER_PARAM structure + ' which contains all information needed + End Select + Return 0 + End Function + ... + ' open the VST editor (e.g. if we are inside a System.Windows.Forms.Form) + BassVst.BASS_VST_EmbedEditor(vstHandle, Me.Handle) + ' we want to get notified for parameter changes etc. + _myVstProc = New VSTPROC(AddressOf YourVstProc) + BassVst.BASS_VST_SetCallback(vstHandle, _myVstProc, IntPtr.Zero) + + + + + + The general VST plugin dispatcher callback delegate). + + The aeffect as retrieved via . + The operation code (OpCode), one of the values. + The index parameter (see the VST SDK for further details). + The value parameter (see the VST SDK for further details). + The user parameter, a pointer to an element, e.g. a string or structure (see the VST SDK for further details). + The optional parameter (see the VST SDK for further details). + See Steinberg VST SDK documentaion for more information. + + This delegate is only used internally within the class and can not be used directly! It is also only supported in the .Net Framework version 2.0 or above! + See Steinberg VST SDK documentaion for more information. + + + + + The VST plugin process callback delegate. Accumulating process mode is deprecated in VST 2.4, use instead. + See Steinberg VST SDK documentaion for more information. + + The aeffect as retrieved via . + An array of pointers to the data (e.g. for stereo channels this will be an IntPtr to an array of 2 element containing the IntPtr to the float values). + An array of pointers to where the data can be written to (e.g. for stereo channels this will be an IntPtr to an array of 2 element containing the IntPtr to the float values). + Number of sample frames to process. + + This delegate is only used internally within the class and can not be used directly! It is also only supported in the .Net Framework version 2.0 or above! + + + + + The VST plugin process callback delegate (non accumulating). + See Steinberg VST SDK documentaion for more information. + + The aeffect as retrieved via . + An array of pointers to the data (e.g. for stereo channels this will be an IntPtr to an array of 2 element containing the IntPtr to the float values). + An array of pointers to where the data can be written to (e.g. for stereo channels this will be an IntPtr to an array of 2 element containing the IntPtr to the float values). + Number of sample frames to process. + + This delegate is only used internally within the class and can not be used directly! It is also only supported in the .Net Framework version 2.0 or above! + + + + + The VST plugin process callback delegate (non accumulating, double-precision). + See Steinberg VST SDK documentaion for more information. + + The aeffect as retrieved via . + An array of pointers to the data (e.g. for stereo channels this will be an IntPtr to an array of 2 element containing the IntPtr to the float values). + An array of pointers to where the data can be written to (e.g. for stereo channels this will be an IntPtr to an array of 2 element containing the IntPtr to the float values). + Number of sample frames to process. + + This delegate is only used internally within the class and can not be used directly! It is also only supported in the .Net Framework version 2.0 or above! + + + + + Set new value of automatable parameter. + + The aeffect as retrieved via . + The parameter index. + The new parameter value (a float value between 0.0 and 1.0 inclusive). + See Steinberg VST SDK documentaion for more information. + + This delegate is only used internally within the class and can not be used directly! It is also only supported in the .Net Framework version 2.0 or above! + + + + + Gets a value of automatable parameter. + + The aeffect as retrieved via . + The parameter index. + The parameter value (a float value between 0.0 and 1.0 inclusive). + + Returns the value of parameter index (a float value between 0.0 and 1.0 inclusive). + This delegate is only used internally within the class and can not be used directly! It is also only supported in the .Net Framework version 2.0 or above! + + + + + BASS.NET API wrapper for BASS_CDG.DLL + Requires: bass_cdg.dll - CDG Add-On - available @ www.un4seen.com. + + + BASS_CDG is an extension to the BASS audio library, enabling the playback of CDG streams. + CD+G (also known as CD+Graphics) is an extension of the compact disc standard that can present low-resolution graphics alongside the audio data on the disc when played on a compatible device. CD+G discs are often used for karaoke machines, which utilize this functionality to present on-screen lyrics for the song contained on the disc. + The CDG format is used in the same way as any of the built-in BASS stream formats. Simply call to load the add-on into BASS and benefit the usage of the standard sample/stream functions. + More information can be found on wikipedia. + + + + + NOT used - all members are static! + + + + + Sets a BASS_CDG config option. + + One of the options. + The parameter value to set with the option. + + + + Sets the window handle to use with the CDG stream (for the graphics output). + + The CDG channel handle (HSTREAM). + The window handle of the control which should be used to display the CDG graphics output. + + + + Gets the current bitmap of the CDG stream (for graphics output). + + The CDG channel handle (HSTREAM). + The attached windows GDI handle of the bitmap image object. + + + + Supported file extensions of the bass_cdg.dll + + + + + Supported file format name of the bass_cdg.dll + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + The disadvantage of this method is, that the standard plugin support for is not working - so you would need to use the native add-on methods! + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + Configuration options to be used with . + + + + + Use a user defined renderer. + value (int): 0=use internal renderer; 1=use user renderer. + + + + + Internal Tag support of the BASS.NET API . + Requires: bass.dll - for better Tag reading support. + + + The BASS audio library has limited support for reading tags, associated with a stream. + This class extends that functionality, allowing you to extract specific TAG information from a stream or file. + The extracted tag values are formatted into a general class structure. + Supported tags are ID3v1, ID3v2, WMA, OGG, RIFF, BWF, MOD, MP4, MF and APE and are evaluated as followed: + MP3, MP2, MP1: first ID3v2, then ID3v1, then APE, then BWF. + OGG: first OGG, then APE. + WMA: only WMA. + MP4, AAC: first MP4, then ID3v2, then APE, then OGG + WAV: RIFF_INFO, then BWF, then ID3v2 + all others: first APE, then OGG, then ID3v2, then ID3v1. + + + + + NOT used - all members are static! + + + + + Gets or Sets, if picture tags should be read. + + Set this value to to not read any picture tags with e.g. the methods. + The default is . + + + + Retrieves the requested tags/headers from a file, if they are available. + + The fully qualified name of the file stream to get the TAG information from. + Returns a new instance if successful. If TAGs could be retrieved successfully is returned. + + Note: This method uses the BASS plug-in system and such supports all formats which are supported by BASS or any of its add-ons. + So make sure to load all needed add-ons via . + This method first evaluates the file name extension. If using with a ".wma" or ".wmv" file and you are using the WMA DRM version, the WMA tags are received immediately. + For all other file types an internal stream handle is created by using the plug-in system and calling . If successful, the TAG_INFO is returned via (see overload list). + All members of the structure will be updated. However, some files and tag structures might not support all members. + This overload + + + Invalid/Unsupported tag version detected. + Invalid syncsafe integer found in tag data. + + Getting TAGs from a file directly: + + TAG_INFO tagInfo = BassTags.BASS_TAG_GetFromFile(fileName); + if ( tagInfo != null ) + { + // display the tags... + } + + + Dim tagInfo As TAG_INFO = BassTags.BASS_TAG_GetFromFile(fileName) + If Not (tagInfo Is Nothing) Then + ' display the tags... + End If + + + + + + Retrieves the requested tags/headers from a file, if they are available. + + The fully qualified name of the file stream to get the TAG information from. + If the property will be set to a default value (filename without extension). + If the flag is used to return an exact value - else the duration might just be good approximation, but the method will perform faster. + Returns a new instance if successful. If could not be found is returned. + + Note: This method uses the BASS plug-in system and such supports all formats which are supported by BASS or any of its add-ons. + So make sure to load all needed add-ons via . + This method first evaluates the file name extension. If using with a ".wma" or ".wmv" file and you are using the WMA DRM version, the WMA tags are received immediately. + For all other file types an internal stream handle is created by using the plug-in system and calling . If successful, the TAG_INFO is returned via (see overload list). + All members of the structure will be updated. However, some files and tag structures might not support all members. + + + Invalid/Unsupported tag version detected. + Invalid syncsafe integer found in tag data. + + Getting TAGs from a file directly: + + TAG_INFO tagInfo = BassTags.BASS_TAG_GetFromFile(fileName, true, true); + if ( tagInfo != null ) + { + // display the tags... + } + + + Dim tagInfo As TAG_INFO = BassTags.BASS_TAG_GetFromFile(fileName, True, True) + If Not (tagInfo Is Nothing) Then + ' display the tags... + End If + + + + + + Retrieves the requested tags/headers from a file, if they are available. + + The fully qualified name of the file stream to get the TAG information from. + If the flag is used to return an exact value - else the duration might just be good approximation, but the method will perform faster. + The class where to put the data. + If TAGs could be retrieved successfully is returned, else is returned. + + Note: This method uses the BASS plug-in system and such supports all formats which are supported by BASS or any of its add-ons. + So make sure to load all needed add-ons via . + This method first evaluates the file name extension. If using with a ".wma" or ".wmv" file and you are using the WMA DRM version, the WMA tags are received immediately. + For all other file types an internal stream handle is created by using the plug-in system and calling . If successful, the TAG_INFO is returned via (see overload list). + Only those members of the structure will be updated which have been found in the file. However, some files and tag structures might not support all members. + + + Invalid/Unsupported tag version detected. + Invalid syncsafe integer found in tag data. + + Getting TAGs from a file directly: + + TAG_INFO tagInfo = BassTags.BASS_TAG_GetFromFile(fileName, true, true); + if ( tagInfo != null ) + { + // display the tags... + } + + + Dim tagInfo As TAG_INFO = BassTags.BASS_TAG_GetFromFile(fileName, True, True) + If Not (tagInfo Is Nothing) Then + ' display the tags... + End If + + + + + + Retrieves the requested tags/headers from a stream channel, if they are available. + + The stream channel to get the TAG information from. + The class where to put the data. + If TAGs could be retrieved successfully is returned, else is returned. + + This method first evaluates the BASS_CTYPE_xxx for the stream, by calling the function internally. + Based on the retrieved a call to the function is made in order to retrieve the pointer to the tags/header data - if available. + Finally this tag pointer is evaluated and the related tag/header data is evaluated. + This method is able to retrieve the following TAGs: + + MP3, MP2, MP1BASS_TAG_ID3V2 first, then BASS_TAG_ID3, then BASS_TAG_APE, then BASS_TAG_RIFF_BEXT. + OGGBASS_TAG_OGG first, then BASS_TAG_APE + WAV, BWFBASS_TAG_RIFF_INFO first, then BASS_TAG_RIFF_BEXT. + MFBASS_TAG_MF. + WMABASS_TAG_WMA + MP4, AAC, ALACBASS_TAG_MP4 first, then BASS_TAG_ID3V2, then BASS_TAG_APE + APE, FLAC, MPC, OFR, WVBASS_TAG_APE first, then BASS_TAG_ID3V2, then BASS_TAG_ID3 + WINAMPBASS_TAG_ID3V2 first, then BASS_TAG_APE + SPX, AC3not available + MODMOD music name and message are evaluated only. + + All members of the structure will be updated. However, some files and tag structures might not support all members. + + The following TAGs are combined in the following order (if multiple TAGs are found): + + BASS_TAG_ID3V2BASS_TAG_ID3 + BASS_TAG_APE + BASS_TAG_ID3V2 + BASS_TAG_ID3BASS_TAG_APE + BASS_TAG_ID3 + BASS_TAG_WMABASS_TAG_WMA + BASS_TAG_OGGBASS_TAG_APE + BASS_TAG_OGG + BASS_TAG_APEBASS_TAG_ID3 + BASS_TAG_APE + BASS_TAG_MP4BASS_TAG_APE + BASS_TAG_ID3V2 + BASS_TAG_MP4 + BASS_TAG_RIFF_INFOBASS_TAG_RIFF_BEXT + BASS_TAG_RIFF_CART + BASS_TAG_ID3V2 + BASS_TAG_RIFF_INFO + + + + Invalid/Unsupported tag version detected. + Invalid syncsafe integer found in tag data. + + + // create a stream + int stream = Bass.BASS_StreamCreateFile(fileName, 0, 0, BASSFlag.BASS_DEFAULT); + // update the tags + TAG_INFO tagInfo = new TAG_INFO(fileName); + if ( BassTags.BASS_TAG_GetFromFile( stream, tagInfo) ) + { + // display the tags... + } + + + ' create a stream + Dim stream As Integer = Bass.BASS_StreamCreateFile(fileName, 0, 0, BASSFlag.BASS_DEFAULT) + Dim tagInfo As New TAG_INFO(fileName) + If BassTags.BASS_TAG_GetFromFile(stream, tagInfo) Then + ' display the tags... + End If + + + + + + Retrieves the requested tags/headers from a URL stream, if they are available. + + The stream to get the TAG information from. + The class where to put the data. + If TAGs could be retrieved successfully is returned, else is returned. + + This method first tries to get streaming header information via BASS_TAG_ICY and BASS_TAG_HTTP. + Then it tries the following tags in that order: BASS_TAG_META, BASS_TAG_OGG, BASS_TAG_APE and BASS_TAG_WMA. + This method is able to retrieve the following TAGs: + + Shoutcast streamingBASS_TAG_ICY and BASS_TAG_META + Icecast streamingBASS_TAG_HTTP and BASS_TAG_OGG + WMA streamingUse instead, since WMA URL stream are created with the file method. + APE streamingBASS_TAG_HTTP and BASS_TAG_APE + + + The following members of the structure will be updated: + + titleWith the detected new stream title, if found. + Note: The 'streamtitle' might be composed within the meta data, e.g. Shoutcast combines the artist name and the real track name together. Shoutcast titles will be split at the first occurence of a " - " seperator. + artistWith the detected new artist, if found. + Note: For Shoutcast stream this will be set as the 'streamtile' will splitted. + albumWith the detected name of the stream, if found (eg. icy-name). + genreWith the detected genre of the stream, if found (eg. icy-genre). + commentWith the detected new stream url, if found (eg. icy-url). + yearWith the detected bitrate, if found (only used with shoutcast streams, eg. icy-br). + + + + + // create a stream + int stream = BASS_StreamCreateURL(url, 0, BASSFlag.BASS_STREAM_STATUS, null, 0); + // update the tags + TAG_INFO tagInfo = new TAG_INFO(url); + if ( BassTags.BASS_TAG_GetFromURL( stream, tagInfo) ) + { + // display the tags... + } + + + ' create a stream + Dim stream As Integer = BASS_StreamCreateURL(url, 0, BASSFlag.BASS_STREAM_STATUS, Nothing, 0) + ' update the tags + Dim tagInfo As New TAG_INFO(url) + If BassTags.BASS_TAG_GetFromURL(stream, tagInfo) Then + ' display the tags... + End If + + + + + + Gets an IntPtr to the memory block containing the meta tag data. + + The stream to get the tags from. + The structure containing the CTYPE, which will be used to find the tags. + Returns the detected type. + An to the tag memory block, or if no tags could be found. + + This method supports the following tags, which are evaluated in the following order: + + MP3, MP2, MP1BASS_TAG_ID3V2 first, then BASS_TAG_ID3, then BASS_TAG_RIFF_BEXT + OGGBASS_TAG_OGG first, then BASS_TAG_APE + WMABASS_TAG_WMA + MP4, AAC, ALACBASS_TAG_MP4 first, then BASS_TAG_ID3V2, then BASS_TAG_APE, then BASS_TAG_OGG + APE, FLAC, MPC, OFR, WVBASS_TAG_APE first, then BASS_TAG_OGG, then BASS_TAG_ID3V2, then BASS_TAG_ID3 + WINAMPBASS_TAG_ID3V2 first, then BASS_TAG_APE, then BASS_TAG_OGG + WAV, SPX, AC3not available + + + + + + Contains a list of ID3v1 audio generes. + + + + + Used with to retrieve information on the current tags of a stream. + + + The following mapping is used with the diferent tag formats to read the content: + + NameMapping + title + ID3v2: TIT2, TT2 + OGG: TITLE + APE: Title + MP4: ©nam + ASF: WM/Title + RIFF: INAM + Alternatives: -- + + artist + ID3v2: TPE1, TP1 + OGG: ARTIST + APE: Artist + MP4: ©ART + ASF: WM/Author + RIFF: IART + Alternatives: ISTR, AUTHOR + + album + ID3v2: TALB, TAL + OGG: ALBUM + APE: Album + MP4: ©alb + ASF: WM/AlbumTitle + RIFF: IPRD + Alternatives: -- + + albumartist + ID3v2: TPE2, TP2 + OGG: ALBUMARTIST + APE: Album Artist + MP4: aART + ASF: WM/AlbumArtist + RIFF: ISBJ + Alternatives: H2_ALBUMARTIST, ENSEMBLE, ORCHESTRA, BAND, PERFORMER, iaar + + track + ID3v2: TRCK, TRK + OGG: TRACKNUMBER + APE: Track + MP4: trkn + ASF: WM/TrackNumber + RIFF: IPRT, ITRK + Alternatives: TRACKNUM + + disc + ID3v2: TPOS, TPA + OGG: DISCNUMBER + APE: Disc + MP4: disk + ASF: WM/PartOfSet + RIFF: IFRM + Alternatives: DISCNUM + + year + ID3v2: TYER, TYE + OGG: DATE + APE: Year + MP4: ©day + ASF: WM/Year + RIFF: ICRD + Alternatives: TDRC, RELEASEDATE, RELEASE DATE + + genre + ID3v2: TCON, TCO + OGG: GENRE + APE: Genre + MP4: ©gen + ASF: WM/Genre + RIFF: IGNR + Alternatives: -- + + copyright + ID3v2: TCOP, TCR + OGG: COPYRIGHT + APE: Copyright + MP4: cprt + ASF: Copyright + RIFF: ICOP + Alternatives: PROVIDER, WM/Provider + + encodedby + ID3v2: TENC, TEN + OGG: ENCODEDBY + APE: EncodedBy + MP4: ©too + ASF: WM/EncodedBy + RIFF: ISFT + Alternatives: VERSION, ENCODED BY, ENCODED-BY, ENCODER, SOFTWARE, TOOL + + publisher + ID3v2: TPUB, TPB + OGG: LABEL + APE: Label + MP4: ----:com.apple.iTunes:LABEL + ASF: WM/Publisher + RIFF: ICMS + Alternatives: PUBLISHER, ORIGINALSOURCE, VENDOR + + composer + ID3v2: TCOM, TCM + OGG: COMPOSER + APE: Composer + MP4: ©wrt + ASF: WM/Composer + RIFF: IENG + Alternatives: ORGANIZATION, WRITER, IMUS + + conductor + ID3v2: TPE3, TP3 + OGG: CONDUCTOR + APE: Conductor + MP4: ----:com.apple.iTunes:CONDUCTOR + ASF: WM/Conductor + RIFF: ITCH + Alternatives: -- + + lyricist + ID3v2: TEXT, TXT + OGG: LYRICIST + APE: Lyricist + MP4: ----:com.apple.iTunes:LYRICIST + ASF: WM/Writer + RIFF: IWRI + Alternatives: TEXTER, SONGWRITER + + remixer + ID3v2: TPE4, TP4 + OGG: REMIXER + APE: MixArtist + MP4: ----:com.apple.iTunes:REMIXER + ASF: WM/ModifiedBy + RIFF: IEDT + Alternatives: ModifiedBy + + producer + ID3v2: TIPL, IPL + OGG: PRODUCER + APE: Producer + MP4: ----:com.apple.iTunes:PRODUCER + ASF: WM/Producer + RIFF: IPRO + Alternatives: -- + + comment + ID3v2: COMM, COM + OGG: COMMENT + APE: Comment + MP4: ©cmt + ASF: WM/Description + RIFF: ICMT + Alternatives: DESCRIPTION + + grouping + ID3v2: TIT1, TT1 + OGG: GROUPING + APE: Grouping + MP4: ©grp + ASF: WM/ContentGroupDescription + RIFF: ISRF + Alternatives: GROUP + + mood + ID3v2: TMOO + OGG: MOOD + APE: Mood + MP4: ----:com.apple.iTunes:MOOD + ASF: WM/Mood + RIFF: IKEY + Alternatives: -- + + rating + ID3v2: POPM + OGG: RATING + APE: Rating + MP4: rtng + ASF: WM/SharedUserRating + RIFF: ISHP + Alternatives: TXXX:RATING, IRTD + + isrc + ID3v2: TSCR + OGG: ISRC + APE: ISRC + MP4: ----:com.apple.iTunes:ISRC + ASF: WM/ISRC + RIFF: ISRC + Alternatives: -- + + bpm + ID3v2: TBPM, TBP + OGG: BPM + APE: BPM + MP4: ----:com.apple.iTunes:BPM + ASF: WM/BeatsPerMinute + RIFF: IBPM + Alternatives: TEMPO, IDPI, tmpo, H2_BPM, BEATSPERMINUTE + + replaygain_track_gain + ID3v2: TXXX:replaygain_track_gain + OGG: replaygain_track_gain + APE: replaygain_track_gain + MP4: ----:com.apple.iTunes:replaygain_track_gain + ASF: replaygain_track_gain + RIFF: IRGG + Alternatives: itgl + + replaygain_track_peak + ID3v2: TXXX:replaygain_track_peak + OGG: replaygain_track_peak + APE: replaygain_track_peak + MP4: ----:com.apple.iTunes:replaygain_track_peak + ASF: replaygain_track_peak + RIFF: IRGP + Alternatives: -- + + + Note: The mapping is performed case insensitive. The Alternatives are only used, if the regular mapping doesn't find any matching entry. + + + + + The song title. + + + + + The Artist name. + + + + + The Album name. + + + + + The Album Artist name (Band/Orchestra/Remixer). + + + + + The Year (as a string, typically in the format YYYY or YYYY-MM). + + + + + The Comment text. + + + + + The Genre (as a string). + + + + + The track number (as a string, either '99' or '99/99'). + + + + + The disc number (as a string, either '99' or '99/99'). + + + + + The Copyright (as a string). + + + + + The EncodedBy (as a string). + + + + + The Composer (as a string). + + + + + The Publisher, Label (as a string). + + + + + The Lyricist, Songwriter (as a string). + + + + + The Remixer, Modifier (as a string). + + + + + The Producer (as a string). + + + + + Beats Per Minute. + + + + + The name of the file (only available, if set in the constructor or manually) + + + + + Keeps optional pictures. + + + + + Keeps all native tags. + + + + + The structure. + + + + + The type of TAG being read (one of ). + + + + + The estimated duration of the track in seconds. + + This value doesn't have to be 100% accurate but is typically a very good estimation. + + + + The estimated bitrate of the track in kBit/sec. + + This value doesn't have to be 100% accurate but is typically a good estimation. + Note: Only usefull with files encoded in CBR (constant bitrate). + + + + The track replaygain gain value in dB between -60.0 and +60.0 dB. + + Set to -100.0 if not present. + + + + The track replaygain peak level value as a float value between 0.0 (silence) and 1.0 (0dB). + + /// Set to -1.0 if not present. + + + + The conductor (or director) of the content. + + + + + Content groups are collections of media to which individual files may belong. For example, an audio file may be a song that is a track on one compact disc that is part of a boxed set. + + + + + The mood of the content. + + + + + The rating of the content (e.g. 0=unrated, 1-20=poor, 21-40=average, 41-60=good, 61-80=very good, 81-100=excellent). + + + + + The International Standard Recording Code (a 12 digit unique alphanumeric number). + + + + + Default constructor (filename must be set manually in order to be available). + + + + + Creates a new instance as a clone of an existing instance. + + The instance to clone. + + + + Constructor already setting the filename (full path) and the title (file name only). + + The filename to remember. + + + + Constructor already setting the filename (full path) and the title (file name only). + + The filename to remember. + If the property will be set to a default value (filename without extension). + + + + Returns a new TAG_INFO instance which is a clone of the current one. + + The cloned instance. + + + + A description of the tag info object (artist - title or filename). + + A description of the tag info object (artist - title or filename). + + + + Clears the collection of native tag entries. + + + + + Returns a certain native tag. + + The name of the native tag to retrieve (case-sensitive!) - e.g. use "TPE1" to query for the artist of ID3v2 tags. + The value of the tag or if tag with that name could be found. + If multiple tags with the same name do exist, only the first tag value will be returned. + + + + Update the tags from a meta data pointer, e.g. when streaming from a URL as triggered by a using BASS_SYNC_META and as returned by . + + The pointer to the memory block containing the meta data, e.g. as returned by . + Set to , if the tags are present in UTF-8 (8-bit), else set to to use ANSI characters (7-bit). + Set to , if a single tag entry is further seperated by ';' (e.g. as for BASS_TAG_META) - in all other cases this should be set to . + If any tag was updated is returned. If nothing was changed will be returned. + + The following members will be updated: + + titleWith the detected new stream title, if found. + Note: For URL streams (Shoutcast, Oddcast) the 'streamtitle' might be composed within the meta data, e.g. Shoutcast combines the artist name and the real track name together. Shoutcast titles will be splitted at the first occurence of a '-' seperator. + artistWith the detected new artist, if found. + Note: For URL streams (Shoutcast, Oddcast) the 'streamtitle' might be composed within the meta data, e.g. Shoutcast combines the artist name and the real track name together. Shoutcast titles will be splitted at the first occurence of a '-' seperator. + albumWith the detected album name of the stream, if found (eg. icy-name). + genreWith the detected genre of the stream, if found (eg. icy-genre). + commentWith the detected new comment, if found (e.g. icy-url). + yearWith the detected year, if found. + bitrateWith the detected bitrate, if found (e.g. icy-br). + Note: For URL streams (Shoutcast, Oddcast), the new url location will be used. + Note: For MIDI lyric text syncs please use the method. + + + + Update tags with a sync proc together with Bass.BASS_StreamCreateURL: + + private SYNCPROC _mySync; + private TAG_INFO _tags; + ... + string url = "http://someurl..."; + int stream = Bass.BASS_StreamCreateURL(url, 0, BASSFlag.BASS_STREAM_STATUS, null, 0); + _tags = new TAG_INFO(url); + // set a sync to get the title updates out of the meta data... + _mySync = new SYNCPROC(MetaSync); + Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_META, 0, _mySync, IntPtr.Zero); + ... + private void MetaSync(int handle, int channel, int data, IntPtr user) + { + // BASS_SYNC_META is triggered on meta changes of SHOUTcast streams + _tags.UpdateFromMETA( Bass.BASS_ChannelGetTags(channel, BASSTag.BASS_TAG_META), false ); + } + + + Private _mySync As SYNCPROC + Private _tags As TAG_INFO + ... + Dim url As String = "http://someurl..." + Dim stream As Integer = Bass.BASS_StreamCreateURL(url, 0, BASSFlag.BASS_STREAM_STATUS, Nothing, 0) + _tags = New TAG_INFO(url) + ' set a sync to get the title updates out of the meta data... + _mySync = New SYNCPROC(AddressOf MetaSync) + Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_META, 0, _mySync, IntPtr.Zero) + ... + Private Sub MetaSync(handle As Integer, channel As Integer, data As Integer, user As IntPtr) + ' BASS_SYNC_META is triggered on meta changes of SHOUTcast streams + _tags.UpdateFromMETA(Bass.BASS_ChannelGetTags(channel, BASSTag.BASS_TAG_META), False) + End Sub + + + + + + Update the tags from a meta data pointer, when using in a using BASS_SYNC_MIDI_LYRIC or BASS_MIDI_MARK_TEXT. + + The instance of the structure from which to update the lyric text, as retrieved form . + If any tag was updated is returned. If nothing was changed will be returned. + + The following members will be updated: + + commentWith the detected new lyric text, if found. + If the lyric text begins with a '/' (slash) character, a new line ('\n')will be added to the comment. + If it begins with a '\' (backslash) character, the comment will be cleared first - in all other cases the lyric text will be appended to the existing comment. + + trackWith the midi track number, if changed. + + + + Update MIDI lyric text in the comment member: + + private SYNCPROC _mySync; + private TAG_INFO _tags; + ... + int midi = BassMidi.BASS_MIDI_StreamCreateFile("test.mid", 0, 0, BASSFlag.BASS_STREAM_AUTOFREE, 44100); + _tags = new TAG_INFO("test.mid"); + // set a sync to get the lyric text updates out of the MIDI data... + _mySync = new SYNCPROC(LyricSync); + Bass.BASS_ChannelSetSync(midi, BASSSync.BASS_SYNC_MIDI_LYRIC, 0, _mySync, IntPtr.Zero); + // get the initial tags + BassTags.BASS_TAG_GetFromFile(midi, _tags); + ... + private void LyricSync(int handle, int channel, int data, IntPtr user) + { + _tags.UpdateFromMIDILyric( BassMidi.BASS_MIDI_StreamGetMark(channel, BASSMIDIMarker.BASS_MIDI_MARK_LYRIC, data) ); + // tags.comment now contains the updated lyric text + Console.Write("{0}\r", _tags.comment) + } + + + Private _mySync As SYNCPROC + Private _tags As TAG_INFO + ... + Dim midiStream As Integer = BassMidi.BASS_MIDI_StreamCreateFile("test.mid", 0, 0, BASSFlag.BASS_STREAM_AUTOFREE, 44100) + _tags = New TAG_INFO("test.mid") + ' set a sync to get the lyric text updates out of the MIDI data... + _mySync = New SYNCPROC(AddressOf LyricSync) + Bass.BASS_ChannelSetSync(midi, BASSSync.BASS_SYNC_MIDI_LYRIC, 0, _mySync, IntPtr.Zero) + ' get the initial tags... + BassTags.BASS_TAG_GetFromFile(midi, _tags) + ... + Private Sub LyricSync(ByVal handle As Integer, ByVal channel As Integer, ByVal data As Integer, ByVal user As IntPtr) + tags.UpdateFromMIDILyric(BassMidi.BASS_MIDI_StreamGetMark(channel, BASSMIDIMarker.BASS_MIDI_MARK_LYRIC, data)) + ' tags.comment now contains the updated lyric text + Console.Write("{0}\r", _tags.comment) + End Sub + + + + + + Adds a native tag. + + The tag name to add. + The tag value to use. + + + + Adds or Replaces a native tag. + + The tag name to replace. + The tag value to use. + If the tag was found its content will be replaced, else a new nativ tag will be created. + + + + Removes a native tag. + + The tag name to replace. + + + + Takes one tag (key=value) and changes the internal members accordingly. + + The tag string to evaluate (in the format: key=value or or key:value) + , if a tag member was changed, else . + + + + Adds a picture tag. + + The tag picture instance to add. + on success - else . + + + + Removes a picture tag. + + The index of the picture to remove. + + + + Removes all picture tags. + + + + + Returns a picture tag. + + The zero-based index (number) of the picture to get. You might use to retrieve the total number of pictures available. + The tag of the picture on success or if no picture is available (at that index). + + + + Returns a picture image. + + The zero-based index (number) of the picture to get. You might use to retrieve the total number of pictures available. + The image of the picture on success or if no picture is available (at that index). + + + + Returns the description of a picture. + + The zero-based index (number) of the picture to access. You might use to retrieve the total number of pictures available. + The description of the picture on success or if no picture is available (at that index). + + + + Returns the type of the picture. + + The zero-based index (number) of the picture to access. You might use to retrieve the total number of pictures available. + The type of the picture on success or if no picture is available (at that index). + + + + Scans the directory of the location for additional pictures and adds them to the internal picture tags (see for details). + + An optional search string, such as "*.jpg" or "Album*.jpg" or to scan for default images. + to add all found images to the picture list or to only add the first found image. + When scanning for default images ( is ) the following order will be used: + + <filename>.jpg + <filename>.gif + <filename>.png + <filename>.bmp + Folder*.jpg + Album*.jpg + <album>.jpg + <album>.gif + <album>.png + <album>.bmp + + In the above list <filename> resp. <album> will be replaced by the actual tag content field values. + This methods adds any found pictures to the internal picture tags. + + + + + Scans the directory of the location for additional pictures and returns any found pictures. + + The fully qualified path and file name to get the picture(s) from. + The optional name of the album tag to use to find a picture file (see below). + An optional search string, such as "*.jpg" or "Album*.jpg" or to scan for default images. + to return all found pictures or to only return the first found picture. + A list of found items or an empty list if no pictures could be found. + When scanning for default images ( is ) the following order will be used: + + <filename>.jpg + <filename>.gif + <filename>.png + <filename>.bmp + Folder*.jpg + Album*.jpg + <album>.jpg + <album>.gif + <album>.png + <album>.bmp + + In the above list <filename> resp. <album> will be replaced by the actual parameter values. + This methods does not add any pictures to the internal picture tags. + + + + + Converts the members of this instance to a WAV RIFF LIST INFO chunk. + + to create the INFO chunk out of the , to create them from the standard members. + The byte array containing the LIST INFO chunk data. + You might use this method to write a RIFF LIST INFO chunk to a wave file using the method. + When creating the INFO chunk from the the standard members, the following mapping is used: + + INFO chunk idContent + INAMtitle + IARTartist + IPRDalbum + ISBJalbumartist + IPRTtrack + IFRMdisc + ICRDyear + IGNRgenre + ICOPcopyright + ISFTencodedby + ICMTcomment + IENGcomposer + ICMSpublisher + ITCHconductor + IWRIlyricist + IEDTremixer + IPROproducer + ISRFgrouping + IKEYmood + ISHPrating + ISRCisrc + IBPMbpm + IRGPreplaygain_track_peak + IRGGreplaygain_track_gain + + + + + + byte[] listData = TAGs.ConvertToRiffINFO(false); + if (listData != null) + BassEnc.BASS_Encode_AddChunk(_encoderHandle, "LIST", listData, listData.Length); + + + Dim listData As Byte() = TAGs.ConvertToRiffINFO(False) + If listData IsNot Nothing Then + BassEnc.BASS_Encode_AddChunk(_encoderHandle, "LIST", listData, listData.Length) + End If + + + + + + Converts the members of this instance to a WAV RIFF BEXT chunk. + + to create the BEXT chunk out of the , to create them from the standard members. + The byte array containing the BEXT chunk data. + You might use this method to write a RIFF BEXT chunk to a wave file using the method. + When creating the BEXT chunk from the the standard members, the following mapping is used: + + BEXT fieldContent + Descriptiontitle + Originatorartist + OriginatorReferenceencodedby + OriginationDateyear + OriginationTimeyear + TimeReference-- + UMID-- + Version1 + CodingHistory-- + + Note: Broadcast Wave Format (bext) native tags are named as above with the prefix 'BWF'. + + + + + byte[] bextData = TAGs.ConvertToRiffBEXT(true); + if (bextData != null) + BassEnc.BASS_Encode_AddChunk(_encoderHandle, "bext", bextData, bextData.Length); + + + Dim bextData As Byte() = TAGs.ConvertToRiffBEXT(True) + If bextData IsNot Nothing Then + BassEnc.BASS_Encode_AddChunk(_encoderHandle, "bext", bextData, bextData.Length) + End If + + + + + + Converts the members of this instance to a WAV RIFF CART chunk. + + to create the CART chunk out of the , to create them from the standard members. + The byte array containing the CART chunk data. + You might use this method to write a RIFF CART chunk to a wave file using the method. + When creating the CART chunk from the the standard members, the following mapping is used: + + CART fieldContent + Version-- + Titletitle + Artistartist + CutIDalbum + ClientIDcopyright + Categorygenre + Classificationgrouping + OutCue-- + StartDate-- + StartTime-- + EndDate-- + EndTime-- + ProducerAppIDencodedby + ProducerAppVersion-- + UserDef-- + LevelReference-- + Timer1-8-- + URL-- + TagTextcomment + + Note: Broadcast Wave Format (cart) native tags are named as above with the prefix 'CART'. + + + + + byte[] cartData = TAGs.ConvertToRiffCART(true); + if (cartData != null) + BassEnc.BASS_Encode_AddChunk(_encoderHandle, "cart", cartData, cartData.Length); + + + Dim cartData As Byte() = TAGs.ConvertToRiffCART(True) + If cartData IsNot Nothing Then + BassEnc.BASS_Encode_AddChunk(_encoderHandle, "cart", cartData, cartData.Length) + End If + + + + + + Returns all native tags. + + A string array containing all native tags as being gathered. + + + + Returns the number of pictures which are available. + + Pictures might not be available to all formats. + If the global is set to picture tags might not be read in. + You can access the available picture tags via the , , or methods. + + + + + A class for reading the tags from an ID3 header. + + + + + Reads the tags from an ID3v2 header. + + The memory pointer to the ID3v2 header. + Invalid syncsafe integer found in ID3v2 data. + + + The 10 byte header looks like this: + struct Id3v2Header + { + char magic[3]; // always "Id3" + char majorVersion; + char minorVersion; + char flags; + int28 size; + }; + The version is always v2.maj.min -- the v2 is implied. + flags currently only defines 4 flags. More on these later. + The int28 type is a 28-bit integer padded out to a + 32-bit integer, to make it sync-safe. It's padded by setting + the most significant bit of each byte to zero. + i.e. it looks like this: + 0xxxxxxx0xxxxxxx0xxxxxxx0xxxxxxx + Integers in Id3v2 are big-endian. + A frame looks like this: + struct Id3v2Frame + { + char frame_id[4]; + int28 size; + char flags[2]; + }; + + + + + + Returns all available TagPictures. + + An array list of instances or + + + + Gets all available Tags from a file (using default language!). + + An array list of instances or . + + + + Represent one tag attribute that can be present in a header of a file. + There are defined explicit convertion operator for every possible data type + represented with this structure. + + + + + Initialize the Tag structure with proper values. + + the index of the attribute + Name of the attribute + WMT_ATTR_DATATYPE enum describing the type of the attribute. + The atrtibute value. This param is an obcjet and must match the + param type, ex. If type is WMT_ATTR_DATATYPE.WMT_TYPE_BOOL val param must be a valid bool and so on. + + + + ToString is overridden to provide the string representation in "name=value" format. + + String represantation of this struct in "name=value" format. + + + + Index of the attribute + + + + + Name of the attribute + + + + + Data type of the attribute + + + + + Read/Write object representing the value of the attribute. + When writing this property the object must match to the DataType + + + + + Gets a string representing the value of the attribute. + + + + + This class represents a picture tag. + + + + + The MIMEType of the picture. + + + + + The type of the picture - one of the values. + + + + + The description of the picture. + + + + + The raw image data of the picture or the UTF-8 encoded location of the picture. + + + If the is set to , this property directly contains the picture image data. + If the is set to , this property contains the link to the picture image as a fully qualified name (UTF-8 encoded). + + + + + The index or number of the related picture tag (-1 = undefined). + + + + + The storage type of the picture . + + + This property denotes where the image data is stored. + specifies, that directly contains the picture image. + specifies, that contains the link to the picture image as a fully qualified name (UTF-8 encoded). + + + + + Creates a picture tag from the given values. + + The index/number of picture. + The MIMEType of the picture. + The PICTURE_TYPE. + The description of the picture. + The raw image data. + The will be set to . + + + + Creates a picture tag from the given values. + + The image to add as a new picture. + The PICTURE_TYPE. + The description of the picture. + The will be set to . + + + + Creates a picture tag as an external link to a file. + + A string that contains the fully qualified name of the file from which to create the picture. + The will be set to . + + + + Creates a picture tag as an external link to a file. + + A string that contains the fully qualified name of the file from which to create the picture. + The type of the picture (one of the values). + The description of the picture. + The will be set to . + + + + Loads a picture from a byte[] Tag! + + The Tag containing the raw byte[] image. + The will be set to . + + + + Loads a picture from a byte[] containing the PIC/FLAC image struct. + + The byte[] containing the PIC/FLAC image struct. + 0=raw image, 1=FLAC structure, 2=APE structure. + The will be set to . + + + + Creates a resized, internal, Jpeg clone of a given picture tag. + + The existing picture tag to create the resized, internal, Jpeg clone from. + The new size of the picture (the effective width and height will be calculated streched to this). + The will be set to ; + the MIMEType will be set to image/jpeg. + + + + Returns the description, picture type and MIMEType of the picture. + + The picture description string. + + + + Returns the MIMEType of a given . + + The image to get the MIMEType from. + The MIMEType of the image. + + + + Returns the MIMEType of a given file by evaluating the file extension. + + The name of the file to get the MIMEType from. + The MIMEType string of the image. + + + + Creates an from the specified file (non locking). + + A string that contains the name of the file from which to create the . + The on success or on error. + + + + Saves an to a given location in a given format (non-locking). + + The image to save. + The filename and path of the file to save the image to. + Specifies the file format of the image. + on success, else is returned. + + + + Returns the related image. + + + + + Picture Type enumeration. + + + + + Picture of a type not specifically listed (unknown or other). + + + + + 32 pixel by 32 pixel file icon. Use only with portable network graphics (PNG) format. + + + + + File icon not conforming to type 1 above. + + + + + Front album cover. + + + + + Back album cover. + + + + + Leaflet page. + + + + + Media, typically this type of image is of the label side of a CD. + + + + + Picture of the lead artist, lead performer, or soloist. + + + + + Picture of one of the artists or performers. + + + + + Picture of the conductor. + + + + + Picture of the band or orchestra. + + + + + Picture of the composer. + + + + + Picture of the lyricist or writer. + + + + + Picture of the recording studio or location. + + + + + Picture taken during a recording session. + + + + + Picture taken during a performance. + + + + + Screen capture from a movie or video. + + + + + A bright colored fish. + + + + + Illustration. + + + + + Logo of the band or artist. + + + + + Logo of the publisher or studio. + + + + + Picture Storage enumeration. + + + + + The picture is stored internally as an image. + + + + + The picture is stored externally as an image link. + + + + + BASS.NET API wrapper for BASS_ADX.DLL + Requires: bass_adx.dll - ADX Add-On - available @ www.un4seen.com. + + + BASS_ADX is an extension to the BASS audio library, enabling the playback of ADX streams. + ADX is a lossy proprietary audio storage and compression format developed by CRI Middleware specifically for use in video games, it is derived from ADPCM. + The ADX format is used in the same way as any of the built-in BASS stream formats. Simply call to load the add-on into BASS and benefit the usage of the standard sample/stream/URL/user functions, or call the /URL/User functions. + More information can be found on wikipedia and here ADX product page. + + + + + NOT used - all members are static! + + + + + + + + + + + + + + + + Creates a sample stream from an ADX file. + This overload implements UNICODE filenames. The BASS_UNICODE flag will be added automatically, since all .Net strings are always unicode. + + Filename for which a stream should be created. + File offset to begin streaming from. + Data length... 0 = use all data up to the end of the file. + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + + + + + + + + + + + + Creates a sample stream from an ADX memory IntPtr. + This overload implements streaming from memory. + + An unmanaged pointer to the memory location as an IntPtr. + Offset to begin streaming from (unused for memory streams, set to 0). + Data length (needs to be set to the length of the memory streams in bytes which should be played). + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + Creates a sample stream from an ADX file via a user callback function. + + File system to use: see . + Any combination of these flags: see . + The user defined file functions (see ). + User instance data to pass to the callback functions. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + See . + + + + + + + + + + + + + + + + + + + + + + + + + + Creates a sample stream from an ADX file on the internet, optionally receiving the downloaded data in a callback. + + URL of the file to stream. Should begin with "http://" or "ftp://". + File position to start streaming from. This is ignored by some servers, specifically when the file length is unknown. + Any combination of these flags: see . + Callback function to receive the file as it is downloaded... = no callback. + User instance data to pass to the callback function. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + Supported file extensions of the bass_adx.dll + + + + + Supported file format name of the bass_adx.dll + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + The disadvantage of this method is, that the standard plugin support for is not working - so you would need to use the native add-on methods! + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + TAG structure of an ADX block to be used with . + + Use 'Marshal.PtrToStructure' to convert a tag pointer to this structure. + + Getting the ADX tag info structure: + + IntPtr p = Bass.BASS_ChannelGetTags(stream, BASSTag.BASS_TAG_ADX_LOOP); + if (p != IntPtr.Zero) + { + BASS_ADX_TAG_LOOP adxLoop = (BASS_ADX_TAG_LOOP)Marshal.PtrToStructure(p, typeof(BASS_ADX_TAG_LOOP)); + ... + } + + + Dim p As IntPtr = Bass.BASS_ChannelGetTags(stream, BASSTag.BASS_TAG_ADX_LOOP) + If p <> IntPtr.Zero Then + Dim adxLoop As BASS_ADX_TAG_LOOP = DirectCast(Marshal.PtrToStructure(p, GetType(BASS_ADX_TAG_LOOP)), BASS_ADX_TAG_LOOP) + ... + End If + + Setting a loop according to the ADX tag data (as given in adxLoop): + + private int _loopSync = 0; + private SYNCPROC _loopSyncCallback; + ... + if (adxLoop.LoopEnabled) + { + _loopSyncCallback = new SYNCPROC(LoopSync); + _loopSync = Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_POS | BASSSync.BASS_SYNC_MIXTIME, + adxLoop.ByteEnd, _loopSyncCallback, new IntPtr(adxLoop.ByteStart)); + } + ... + // to remove the loop call this + Bass.Bass.BASS_ChannelRemoveSync(stream, _loopSync); + ... + // the sync callback + private void LoopSync(int syncHandle, int channel, int data, IntPtr user) + { + // move the position to the start (which is given in the user data) + Bass.BASS_ChannelSetPosition(channel, user.ToInt64()); + } + + + Private _loopSync As Integer = 0 + Private _loopSyncCallback As SYNCPROC + ... + If adxLoop.LoopEnabled Then + _loopSyncCallback = New SYNCPROC(AddressOf LoopSync); + _loopSync = Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_POS Or BASSSync.BASS_SYNC_MIXTIME, + adxLoop.ByteEnd, _loopSyncCallback, New IntPtr(adxLoop.ByteStart)) + End If + ... + ' to remove the loop call this + Bass.Bass.BASS_ChannelRemoveSync(stream, _loopSync) + ... + ' the sync callback + Private Sub LoopSync(ByVal handle As Integer, ByVal channel As Integer, + ByVal data As Integer, ByVal user As IntPtr) + ' move the position to the start (which is given in the user data) + Bass.BASS_ChannelSetPosition(channel, user.ToInt64()) + End Sub + + + + + + , if looping is enabled - else . + + + + + The sample start position. + + + + + The byte start position. + + + + + The sample end position. + + + + + The byte end position. + + + + + BASS.NET API wrapper for BASS_AC3.DLL + Requires: bass_ac3.dll - Dolby Digital AC-3 Codec (AC3) Add-On - available @ www.un4seen.com. + + + BASS_AC3 is an extension to the BASS audio library, enabling the playback of AC-3 streams. + AC-3, often referred to as Dolby Digital, is Dolby's third digital audio coding technology based on a perceptual coding method. It is more advanced than AC-2 and delivers up to 5.1 discrete channels of surround sound in less space than stereo PCM. + The AC-3 format is used in the same way as any of the built-in BASS stream formats. Simply call to load the add-on into BASS and benefit the usage of the standard sample/stream/URL/user functions, or call the /URL/User functions. + More information can be found on www.dolby.com. + + + + + NOT used - all members are static! + + + + + + + + + + + + + + + + Creates a sample stream from a Dolby Digital AC-3 file. + This overload implements UNICODE filenames. The BASS_UNICODE flag will be added automatically, since all .Net strings are always unicode. + + Filename for which a stream should be created. + File offset to begin streaming from. + Data length... 0 = use all data up to the end of the file. + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + + + + + + + + + + + + Creates a sample stream from a Dolby Digital AC-3 memory IntPtr. + This overload implements streaming from memory. + + An unmanaged pointer to the memory location as an IntPtr. + Offset to begin streaming from (unused for memory streams, set to 0). + Data length (needs to be set to the length of the memory streams in bytes which should be played). + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + Creates a sample stream from a Dolby Digital AC-3 file via a user callback function. + + File system to use: see . + Any combination of these flags: see . + The user defined file functions (see ). + User instance data to pass to the callback functions. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + See . + + + + + + + + + + + + + + + + + + + + + + + + + + Creates a sample stream from a Dolby Digital AC-3 file on the internet, optionally receiving the downloaded data in a callback. + + URL of the file to stream. Should begin with "http://" or "ftp://". + File position to start streaming from. This is ignored by some servers, specifically when the file length is unknown. + Any combination of these flags: see . + Callback function to receive the file as it is downloaded... = no callback. + User instance data to pass to the callback function. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + Supported file extensions of the bass_ac3.dll + + + + + Supported file format name of the bass_ac3.dll + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + The disadvantage of this method is, that the standard plugin support for is not working - so you would need to use the native add-on methods! + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + BASS.NET API helper and misc. class containing some general useful methods. + + Contains basically some generic converter utilities. + + + + NOT used - all members are static! + + + + + Returns an signed Int16 value which is composed out of a low and high byte. + + The significant part for the lower 8-bit. + The significant part for the higher 8-bit. + The combined signed Int16 value. + + + + Returns an signed Int32 value which is composed out of a low and high value. + + The significant part for the lower 16-bit. + The significant part for the higher 16-bit. + The combined signed Int32 value. + + + + Returns an signed Int32 value which is composed out of a low and high value. + + The significant part for the lower 16-bit. + The significant part for the higher 16-bit. + The combined signed Int32 value. + + + + Returns an signed Int64 value which is composed out of a low and high value. + + The significant part for the lower 16-bit. + The significant part for the higher 16-bit. + The combined signed Int64 value. + + + + Returns an signed Int64 value which is composed out of a low and high value. + + The significant part for the lower 16-bit. + The significant part for the higher 16-bit. + The combined signed Int64 value. + + + + Returns the higher 16-bit of an signed Int32 as a short value. + + The signed Int32 value from which to extract the higher significant 16-bit. + The higher 16-bit value as a short. + + + + Returns the higher 16-bit of an signed Int32 as an integer value. + + The signed Int32 value from which to extract the higher significant 16-bit. + The higher 16-bit value as an integer. + + + + Returns the higher 32-bit of an signed Int64 as an integer value. + + The signed Int64 value from which to extract the higher significant 32-bit. + The higher 32-bit value as an integer. + + + + Returns the lower 16-bit of an signed Int32 as a short value. + + The signed Int32 value from which to extract the lower significant 16-bit. + The lower 16-bit value as a short. + + + + Returns the lower 16-bit of an signed Int32 as an integer value. + + The signed Int32 value from which to extract the lower significant 16-bit. + The lower 16-bit value as an integer. + + + + Returns the lower 32-bit of an signed Int64 as an integer value + + The signed Int64 value from which to extract the lower significant 32-bit. + The lower 32-bit value as an integer + + + + Converts any integer level value to its dB value. + + The integer level to convert. + The maximum value allowed as an integer level value (e.g. use 32768 for stream levels) + The dB value (from 0dB to -infinite). + If you pass a level greater than maxLevel positive dB values will be returned. + + + + Converts any level value to its dB value. + + The level to convert, as a double value. + The maximum value allowed as a double level value (e.g. use 32768.0 for 16-bit stream levels or use 1.0 for 32-bit floating streams). + The dB value (from 0dB to -infinite). + If you pass a level greater than maxLevel positive dB values will be returned. + + + + Converts any dB level value to its level value (integer). + + The dB level to convert. + The maximum value allowed as an integer level value (e.g. use 32768 for stream levels) + The integer level value (from 0 to maxLevel). + If you pass a positive dB value then the return value will be greater than maxLevel. + + + + Converts any dB level value to its level value (double). + + The dB level to convert. + The maximum value allowed as a double level value (e.g. use 1.0 for floating-point stream levels) + The double level value (from 0 to maxLevel). + If you pass a positive dB value then the return value will be greater than maxLevel. + + + + Converts a second value as reveived by to a string representation. + + A value representing seconds. + The seconds as a string in the format: [-][d.]hh:mm:ss[.ff] + + + + Converts a second value as reveived by to a string representation. + + A value representing seconds. + One of the following constants: + + HHMMhours:minutes, e.g. 00:03 + HHMMSShours:minutes:seconds, e.g. 00:03:17 + MMSSminutes:seconds, e.g. 03:17 + MMSSFFminutes:seconds.milliseconds, e.g. 03:17.25 + MMSSFFFminutes:seconds.milliseconds, e.g. 03:17.257 + MMSSFminutes:seconds.milliseconds, e.g. 03:17.2 + HHMMSSFFhours:minutes:seconds.milliseconds, e.g. 00:03:17.25 + HHMMSSFFFhours:minutes:seconds.milliseconds, e.g. 00:03:17.257 + HHMMSSFhours:minutes:seconds.milliseconds, e.g. 00:03:17.2 + SMPTE24hours:minutes:seconds:frames (with 24fps) + SMPTE25hours:minutes:seconds:frames (with 25fps) + SMPTE30hours:minutes:seconds:frames (with 30fps) + SMPTE50hours:minutes:seconds:frames (with 50fps) + SMPTE60hours:minutes:seconds:frames (with 60fps) + all othersWill be converted according to the standard DateTimeFormatInfo pattern as specified in the parameter. + + + The seconds as a string in the given format. + + + + Returns the index of a specific frequency for FFT data. + + The frequency (in Hz) for which to get the index. + The FFT data length (e.g. 4096 for BASS_DATA_FFT4096). + The sampling rate of the device or stream (e.g. 44100). + The index within the FFT data array (max. to length/2 -1). + Example: If the stream is 44100Hz, then 16500Hz will be around bin 191 of a 512 sample FFT (512*16500/44100). + Or, if you are using BASS_DATA_FFT4096 on a stream with a sample rate of 44100 a tone at 540Hz will be at: 540*4096/44100 = 50 (so a bit of the energy will be in fft[51], but mostly in fft[50]). + + + + + Returns the frequency of a specific index in FFT data. + + The index within the FFT data array (half the requested). + The FFT data length (e.g. 4096 for BASS_DATA_FFT4096). + The sampling rate of the device or stream (e.g. 44100). + The frequency (in Hz) which is represented by the index. + Example: If the stream is 44100Hz, then bin 191 of a 512 sample FFT (191*44100/512) will represent 16451Hz. + Or, if you are using BASS_DATA_FFT4096 on a stream with a sample rate of 44100 an index of 50 will represent a tone of 538Hz: 50*44100/4096 = 50. + + + + + Converts an 8-bit unsigned sample to an unsigned 8-bit sample. + + The unsigned 8-bit sample to convert. + A byte array representing the converted 8-bit unsigned sample (byte[1]). + + + + Converts a 16-bit signed sample to an 8-bit unsigned sample. + + The 16-bit signed sample to convert. + A byte array representing the converted 8-bit sample (byte[1]). + + + + Converts a float 32-bit signed sample to an 8-bit unsigned sample. + + The 32-bit signed sample to convert. + A byte array representing the converted 8-bit unsigned sample (byte[1]). + Note: values greater 1.0 or less than -1.0 are capped. + + + + Converts an 8-bit unsigned sample to a 16-bit signed sample. + + The 8-bit unsigned sample to convert. + A byte array representing the converted 16-bit signed sample (byte[2]). + The byte order is represented in the "Little Endian" format as saved on Intel platforms (meaning lower byte first, the LSB is stored at index 0). + If you need a "Big Endian" format just traverse the array from the back. + + + + Converts a 16-bit signed sample to a 16-bit signed sample. + + The 16-bit signed sample to convert. + A byte array representing the converted 16-bit signed sample (byte[2]). + The byte order is represented in the "Little Endian" format as saved on Intel platforms (meaning lower byte first, the LSB is stored at index 0). + If you need a "Big Endian" format just traverse the array from the back. + + + + Converts a float 32-bit signed sample to a 16-bit signed sample. + + The 32-bit signed sample to convert. + A byte array representing the converted 16-bit signed sample (byte[2]). + The byte order is represented in the "Little Endian" format as saved on Intel platforms (meaning lower byte first, the LSB is stored at index 0). + If you need a "Big Endian" format just traverse the array from the back. + Note: values greater 1.0 or less than -1.0 are capped. + + + + + Converts an 8-bit unsigned sample to a 24-bit signed sample. + + The 8-bit unsigned sample to convert. + A byte array representing the converted 24-bit signed sample (byte[3]). + The byte order is represented in the "Little Endian" format as saved on Intel platforms (meaning lower byte first, the LSB is stored at index 0). + If you need a "Big Endian" format just traverse the array from the back. + + + + Converts a 16-bit signed sample to a 24-bit signed sample. + + The 16-bit signed sample to convert. + A byte array representing the converted 24-bit signed sample (byte[3]). + The byte order is represented in the "Little Endian" format as saved on Intel platforms (meaning lower byte first, the LSB is stored at index 0). + If you need a "Big Endian" format just traverse the array from the back. + + + + Converts a float 32-bit signed sample to a 24-bit signed sample. + + The 32-bit signed sample to convert. + A byte array representing the converted 24-bit signed sample (byte[3]). + The byte order is represented in the "Little Endian" format as saved on Intel platforms (meaning lower byte first, the LSB is stored at index 0). + If you need a "Big Endian" format just traverse the array from the back. + Note: values greater 1.0 or less than -1.0 are capped. + + + + + Converts an 8-bit unsigned sample to a float 32-bit signed sample. + + The 8-bit unsigned sample to convert. + A float 32-bit signed value representing the converted 8-bit unsigned sample. + + + + Converts a 16-bit signed sample to a float 32-bit signed sample. + + The 16-bit signed sample to convert. + A float 32-bit signed value representing the converted 16-bit signed sample. + + + + Converts a byte array (in "Little Endian" notation) to a float 32-bit signed sample. + + The byte array sample to convert (must by in "Little Endian", low byte first notation). + A float 32-bit signed value representing the converted sample. + The length of the byte array determines the value to convert. A length of 1 will be treated as an 8-bit sample, a length of 2 will be treated as a 16-bit sample, a length of 3 will be treated as a 24-bit sample etc. + + + + Converts a byte array (in "Little Endian" notation) to a 24-bit signed sample. + + The byte array sample to convert (must by in "Little Endian", low byte first notation). + A int 24-bit signed value representing the converted sample. + The length of the byte array must be at least 3 (however only the last 3 elements are evaluated). + + + + Converts a byte array (in "Little Endian" notation) to a 16-bit signed sample. + + The byte array sample to convert (must by in "Little Endian", low byte first notation). + A short 16-bit signed value representing the converted sample. + The length of the byte array must be at least 2 (however only the last 2 elements are evaluated). + + + + Converts a byte array (in "Little Endian" notation) to an 8-bit unsigned sample. + + The byte array sample to convert (must by in "Little Endian", low byte first notation). + A byte 8-bit unsigned value representing the converted sample. + The length of the byte array must be at least 1 (however only the last element is evaluated). + + + + Calculates a new samplerate according to a shift of an original samplerate by a number of semitones. + + A semitone, or half-step is a musical interval. An octave is 12 semitones wide. + Changing a samplerate in semitones will result in faster resp. slower playback - speed. + The original samplerate which should be changed. + The number of semitones for which the original samplerate should be changed (negative values will slow down, positve numbers will fasten). + The resulting samplerate which was changed by the number of given semitones. + + + + Calculates the length of one beat for a given BPM value. + + The BPM value to translate. + The length in seconds of one beat (or -1 if bpm is zero). + + + + Calculates the BPM value which represented the given length for one beat. + + The length of one beat in seconds. + The translated BPM value (or -1 if seconds is zero). + + + + Converts a byte array to a hex string. + + The buffer to convert. + The converted hex string. + + + + Converts a hex string to a byte array. + + The hex string to convert in the format 'XX XX XX... XX'. + The length of the resulting string (use -1 to convert all). + The converted byte array. + + If specifies more elements than contained in the + the resulting byte array will be padded by zeros. + + + + + Translates an IntPtr into a .NET managed string. + Sometime BASS returns an IntPtr which actually represents a pointer to a memory block containing a null-terminated Ansi *char (string, 8-bit). + This method does this translation for you and returns the actual string. + + The IntPtr which represents the address of the first character of the unmanaged *char (string, 8-bit). + The translated unicode string. + This method actually expands the original 8-bit chars to unicode 16-bit chars as required by .NET (since here each string a unicode ;-). + + + + Translates an IntPtr into a .NET managed string. + Sometime BASS returns an IntPtr which actually represents a pointer to a memory block containing a null-terminated Ansi *char (string, 8-bit). + This method does this translation for you and returns the actual string. + + The IntPtr which represents the address of the first character of the unmanaged *char (string, 8-bit). + The number of bytes to decode. + The translated unicode string. + This method actually expands the original 8-bit chars to unicode 16-bit chars as required by .NET (since here each string a unicode ;-). + + + + Translates an IntPtr into a .NET managed string. + Sometime BASS returns an IntPtr which actually represents a pointer to a memory block containing a null-terminated Unicode *char (string, 16-bit). + This method does this translation for you and returns the actual string. + + The IntPtr which represents the address of the first character of the unmanaged *char (string, 16-bit). + The translated unicode string. + This method actually expands the original chars to unicode 16-bit chars as required by .NET (since here each string a unicode ;-). + + + + Translates an IntPtr into a .NET managed string. + Sometime BASS returns an IntPtr which actually represents a pointer to a memory block containing a null-terminated Unicode *char (string, 16-bit). + This method does this translation for you and returns the actual string. + + The IntPtr which represents the address of the first character of the unmanaged *char (string, 16-bit). + The number of bytes to decode. + The translated unicode string. + This method actually expands the original chars to unicode 16-bit chars as required by .NET (since here each string a unicode ;-). + + + + Translates an IntPtr into a .NET managed string. + Sometime BASS returns an IntPtr which actually represents a pointer to a memory block containing a null-terminated UTF-8 *char (string, 16-bit). + This method does this translation for you and returns the actual string. + + The IntPtr which represents the address of the first character of the unmanaged *char (string, UTF-8, 16-bit). + Returns the number of bytes read (the length of the decoded string). + The translated unicode string. + + + + Translates an IntPtr into a .NET managed object of a given . + Sometime BASS returns a pointer which actually represents a memory block containing a structured object. + This method does this translation for you and returns the actual object. + + The pointer which represents the address of the structured object. + The of object to be created. This type object must represent a formatted class or structure. + The managed object of the specified type. + + + + Returns the version of the BASS.NET API (Bass.Net.dll) + + The version of the Bass.Net.dll + + + + Retrieves an array of strings from a given unmanaged memory location. + NOTE: This method evaluates the pointer as 'a series/array of null-terminated Ansi strings. + + The pointer to the unmanaged memory block. + or an array of strings. Each array element will represent one text as obtained from the IntPtr. + + + + Retrieves an array of strings from a given unmanaged memory location. + NOTE: This method evaluates the pointer as 'a series/array of null-terminated UTF-8 strings. + + The pointer to the unmanaged memory block. + or an array of strings. Each array element will represent one text as obtained from the IntPtr. + + + + Retrieves an array of strings from a given unmanaged memory location. + NOTE: This method evaluates the pointer as 'a series/array of null-terminated UNICODE strings. + + The pointer to the unmanaged memory block. + or an array of strings. Each array element will represent one text as obtained from the IntPtr. + + + + Retrieves an array of int from a given unmanaged memory location. + NOTE: This method evaluates the pointer as 'a series/array of Int32 values terminated by a 0 value. + + The pointer to the unmanaged memory block. + or an array of int. Each array element will represent one Int32 value as obtained from the IntPtr. + + + + Retrieves an array of int from a given unmanaged memory location. + NOTE: This method evaluates the pointer as 'a series/array of Int16 values terminated by a 0 value. + + The pointer to the unmanaged memory block. + or an array of int. Each array element will represent one Int16 value as obtained from the IntPtr. + + + + Copies the contents of a managed string into unmanaged memory, + converting into ANSI format as it copies and appends a null-terminator. + + The managed string to copy to . + The address, in unmanaged memory, to where should be copied. + + + + Copies the contents of a managed string into unmanaged memory + and appends a null-terminator. + + The managed string to copy to . + The address, in unmanaged memory, to where should be copied. + + + + Copies the contents of a managed string into unmanaged memory, + converting into UFT-8 format as it copies and appends a null-terminator. + + The managed string to copy to . + The address, in unmanaged memory, to where should be copied. + + + + Copies the contents of a managed string array into unmanaged memory, + converting each element into ANSI format as it copies and appends a null-terminator. + + The managed string array to copy to . + The address, in unmanaged memory, to where should be copied. + Add a carriage return and line feed ("\r\n") to each string element if missing? + An additional final null-terminator is added as well, so that the last element will end with + a double null-terminator. + Note, that empty string array elements will be skipped. + + + + Copies the contents of a managed string array into unmanaged memory + and appends a null-terminator. + + + + + An additional final null-terminator is added as well, so that the last element will end with a + a double null-terminator. + Note, that empty array elements will be skipped. + + + + Copies the contents of a managed string array into unmanaged memory, + converting each element into UTF-8 format as it copies and appends a null-terminator. + + The string array + + + An additional final null-terminator is added as well, so that the last element will end with a + a double null-terminator. + Note, that empty array elements will be skipped. + + + + Converts a channel number to a string. + + The number of channels. + The description of number of channels. + + + + Converts a to a character representation describing the channel type or file type. Returns e.g. 'WMA', 'FLAC', 'MP3' etc. + + The for which to get the description. + The description of the channel type. + + + + Converts a to a character representation describing the tag type. Returns e.g. 'ID3v1', 'ID3v2', 'WMA', 'APE' etc. + + The for which to get the description. + The description of the tag type. + + + + Returns the supported stream file extensions of the given add-on file (e.g. "bassflac.dll"). + Use to retrieve the native supported stream file extensions of Bass. + Use "music" to retrive the native supported music file extensions of Bass. + + The file name and/or path of the bass add-on dll from which to retrieve the supported file extensions (or or "music"). + A list of supported file extensions (pattern-like, semicolon-seperated, e.g. "*.wma;*.wmv"). + + Note: This list reports a set of file extensions which might be supported. + There is no guarantee that the list is complete or might contain formats not being supported on your particular OS/machine (due to additional or missing audio codecs). + + + + + Returns the supported stream file name of the given add-on file (e.g. "bassflac.dll"). + Use to retrieve the native supported stream file name of Bass. + Use "music" to retrive the native supported music name of Bass. + + The file name and/or path of the bass add-on dll from which to retrieve the supported file name (or or "music"). + The name of the supported audio format (e.g. "Windows Media Audio"). + + + + Returns the supported stream file extensions for all loaded plugins. + + The hash table as returned by the method. + , if also the native BASS formats should be added. + The supported stream file extension string (*.ext1;*.ext2;...*.extN) + This method uses internally and might include all native BASS extensions. + Note: This list reports a set of file extensions which might be supported. + There is no guarantee that the list is complete or might contain formats not being supported on your particular OS/machine (due to additional or missing audio codecs). + + + + Dictionary<int, string> loadedPlugIns = Bass.BASS_PluginLoadDirectory(dir); + string exts = Utils.BASSAddOnGetSupportedFileExtensions(loadedPlugIns, true); + + + Dim loadedPlugIns As Dictionary(Of Integer, String) = Bass.BASS_PluginLoadDirectory(dir) + Dim exts As String = Utils.BASSAddOnGetSupportedFileExtensions(loadedPlugIns, True) + + + + + + Returns a file filter which can be used in a standard 'OpenFileDialog'. + + The hash table as returned by the method. + The name of the first entry which will describe all available formats. Or , if only the plain formats should be returned. + The file filter string which can be used in a standard 'OpenFileDialog' in the format: + allFormatName|AllExtensions|FormatName1|externtions1|FormatName2|externtions2... + This method uses and internally and also includes all native BASS formats. + Note: This list reports a set of file extensions which might be supported. + There is no guarantee that the list is complete or might contain formats not being supported on your particular OS/machine (due to additional or missing audio codecs). + + + + Dictionary<int, string> loadedPlugIns = Bass.BASS_PluginLoadDirectory(dir); + openFileDialog.Filter = Utils.BASSAddOnGetSupportedFileFilter(loadedPlugIns, "All supported Audio Files"); + + + Dim loadedPlugIns As Dictionary(Of Integer, String) = Bass.BASS_PluginLoadDirectory(dir) + openFileDialog.Filter = Utils.BASSAddOnGetPluginFileFilter(loadedPlugIns, "All supported Audio Files") + + + + + + Returns a file filter which can be used in a standard 'OpenFileDialog'. + + The hash table as returned by the method. + The name of the first entry which will describe all available formats. Or , if only the plain formats should be returned. + , if also the native BASS formats should be added. + The file filter string which can be used in a standard 'OpenFileDialog' in the format: + allFormatName|AllExtensions|FormatName1|externtions1|FormatName2|externtions2... + This method uses and internally. + Note: This list reports a set of file extensions which might be supported. + There is no guarantee that the list is complete or might contain formats not being supported on your particular OS/machine (due to additional or missing audio codecs). + + + + Dictionary<int, string> loadedPlugIns = Bass.BASS_PluginLoadDirectory(dir); + openFileDialog.Filter = Utils.BASSAddOnGetSupportedFileFilter(loadedPlugIns, null, false); + + + Dim loadedPlugIns As Dictionary(Of Integer, String) = Bass.BASS_PluginLoadDirectory(dir) + openFileDialog.Filter = Utils.BASSAddOnGetPluginFileFilter(loadedPlugIns, Nothing, False) + + + + + + Returns a file filter which can be used in a standard 'OpenFileDialog'. + + The hash table as returned by the method. + The name of the first entry which will describe all available formats. Or , if only the plain formats should be returned. + The file filter string which can be used in a standard 'OpenFileDialog' in the format: + allFormatName|AllExtensions|FormatName1|externtions1|FormatName2|externtions2... + This method uses and internally and also includes all native BASS formats. + Note: This list reports a set of file extensions which might be supported. + There is no guarantee that the list is complete or might contain formats not being supported on your particular OS/machine (due to additional or missing audio codecs). + + + + Dictionary<int, string> loadedPlugIns = Bass.BASS_PluginLoadDirectory(dir); + openFileDialog.Filter = Utils.BASSAddOnGetPluginFileFilter(loadedPlugIns, "All supported Audio Files"); + + + Dim loadedPlugIns As Dictionary(Of Integer, String) = Bass.BASS_PluginLoadDirectory(dir) + openFileDialog.Filter = Utils.BASSAddOnGetPluginFileFilter(loadedPlugIns, "All supported Audio Files") + + + + + + Returns a file filter which can be used in a standard 'OpenFileDialog'. + + The hash table as returned by the method. + The name of the first entry which will describe all available formats. Or , if only the plain formats should be returned. + , if also the native BASS formats should be added. + The file filter string which can be used in a standard 'OpenFileDialog' in the format: + allFormatName|AllExtensions|FormatName1|externtions1|FormatName2|externtions2... + This method uses and internally. + Note: This list reports a set of file extensions which might be supported. + There is no guarantee that the list is complete or might contain formats not being supported on your particular OS/machine (due to additional or missing audio codecs). + + + + Dictionary<int, string> loadedPlugIns = Bass.BASS_PluginLoadDirectory(dir); + openFileDialog.Filter = Utils.BASSAddOnGetPluginFileFilter(loadedPlugIns, null, false); + + + Dim loadedPlugIns As Dictionary(Of Integer, String) = Bass.BASS_PluginLoadDirectory(dir) + openFileDialog.Filter = Utils.BASSAddOnGetPluginFileFilter(loadedPlugIns, Nothing, False) + + + + + + Checks if a certain file is supported by the currently loaded add-ons. + + The hash table as returned by the method or to only check BASS extensions. + The audio filename to check, + , if the audio file is supported by any of the loaded plugins. + This method uses internally. + Note: There is no guarantee that the check is complete or might contain formats not being supported on your particular OS/machine (due to additional or missing audio codecs). + + + + + Returns the absolute signed maximum value of two values. + + The first value to compare. + The second value to compare. + The signed value of the parameter whose absolute value is greater. + The two values are compared by their absolute unsigned value but are returned with their signed value. + E.g. -10000 will be returned by comparing -10000 and +8000. + + + + Returns the absolute signed maximum value of two values. + + The first value to compare. + The second value to compare. + The signed value of the parameter whose absolute value is greater. + The two values are compared by their absolute unsigned value but are returned with their signed value. + E.g. -10000 will be returned by comparing -10000 and +8000. + + + + Applies a dither to a single sample value. + + The sample data to add a dither to (e.g. an 8- or 16-bit sample value as a double value). + The bit depth factor for the dither (typically between 0.3 and 0.9). + The maximum sample data range (e.g. 256 for 8-bit samples or 32768 for 16-bit samples). + The dithered sample value: + Dithering adds a low level white noise to the sample data before truncating for the purpose of minimizing quantization error. + Dithering here is implemented as a triangular probability density function (TPDF), actually a factor-bit triangular dither. + All parameters here are implemented as double values for maximum precision and performance. + However, you might also pass 8-bit(byte) or 16-bit(short) values and then simply cast back the return value. + + + + + Equivalent to , but with individual offset and length. + + The 16-bit buffer to get the level from. + The number of channels to use (1=mono, 2=stereo). In case of mono the left and right channel will contain the same value. + The starting index (sample offset, not byte offset!) within the buffer from where to to get the level (use -1 to start from the beginning). + Number of samples (not bytes!) to use (startIndex + length must be less than the buffer size, use -1 to scan the whole buffer size). + If successful, the level of the left channel is returned in the low word (low 16-bits), and the level of the right channel is returned in the high word (high 16-bits). If the channel is mono, then the low word is duplicated in the high word. + + Structure of the return value (int = 32-bit): + + | 32-bit | + | right-peak | left-peak | + + + Each peak level ranges linearly from 0 (silent) to +32767 (max). + + + + + Equivalent to , but with individual offset and length. + + The 16-bit buffer to get the level from. + The number of channels to use (1=mono, 2=stereo). In case of mono the left and right channel will contain the same value. + The starting index (sample offset, not byte offset!) within the buffer from where to to get the level (use -1 to start from the beginning). + Number of samples (not bytes!) to use (startIndex + length must be less than the buffer size, use -1 to scan the whole buffer size). + If successful, the level of the left channel is returned in the low Dword (low 32-bits), and the level of the right channel is returned in the high Dword (high 32-bits). + Each Dword (32-bit) carries the maximum peak level value in the high word (high 16-bit) and the the minimum peak level value in the low word (low 16-bit). + If the channel is mono, then the low Dword is duplicated in the high Dword. + + Structure of one element (long = 64-bit): + + | 64-bit | + | right | left | + |max.peak|min.peak|max.peak|min.peak| + + + Each peak level ranges linearly from -32768 to 0 (silent) to +32767. + + + + + Equivalent to , but with individual offset and length. + + The 32-bit buffer to get the level from. + The number of channels to use (1=mono, 2=stereo). In case of mono the left and right channel will contain the same value. + The starting index (sample offset, not byte offset!) within the buffer from where to to get the level (use -1 to start from the beginning). + Number of samples (not bytes!) to use (startIndex + length must be less than the buffer size, use -1 to scan the whole buffer size). + If successful, the level of the left channel is returned in the low word (low 16-bits), and the level of the right channel is returned in the high word (high 16-bits). If the channel is mono, then the low word is duplicated in the high word. + + Structure of the return value (int = 32-bit): + + | 32-bit | + | right-peak | left-peak | + + + Each peak level ranges linearly from 0 (silent) to +32767 (max). + + + + + Equivalent to , but with individual offset and length. + + The 32-bit buffer to get the level from. + The number of channels to use (1=mono, 2=stereo). In case of mono the left and right channel will contain the same value. + The starting index (sample offset, not byte offset!) within the buffer from where to to get the level (use -1 to start from the beginning). + Number of samples (not bytes!) to use (startIndex + length must be less than the buffer size, use -1 to scan the whole buffer size). + If successful, the level of the left channel is returned in the low Dword (low 32-bits), and the level of the right channel is returned in the high Dword (high 32-bits). + Each Dword (32-bit) carries the maximum peak level value in the high word (high 16-bit) and the the minimum peak level value in the low word (low 16-bit). + If the channel is mono, then the low Dword is duplicated in the high Dword. + + Structure of one element (long = 64-bit): + + | 64-bit | + | right | left | + |max.peak|min.peak|max.peak|min.peak| + + + Each peak level ranges linearly from -32768 to 0 (silent) to +32767. + + + + + Equivalent to , but with individual offset and length. + + The 8-bit buffer to get the level from. + The number of channels to use (1=mono, 2=stereo). In case of mono the left and right channel will contain the same value. + The starting index (sample offset, not byte offset!) within the buffer from where to to get the level (use -1 to start from the beginning). + Number of samples (not bytes!) to use (startIndex + length must be less than the buffer size, use -1 to scan the whole buffer size). + If successful, the level of the left channel is returned in the low word (low 16-bits), and the level of the right channel is returned in the high word (high 16-bits). If the channel is mono, then the low word is duplicated in the high word. + + Structure of the return value (int = 32-bit): + + | 32-bit | + | right-peak | left-peak | + + + Each peak level ranges linearly from 0 (silent) to +32767 (max). + + + + + Equivalent to , but with individual offset and length. + + The 8-bit buffer to get the level from. + The number of channels to use (1=mono, 2=stereo). In case of mono the left and right channel will contain the same value. + The starting index (sample offset, not byte offset!) within the buffer from where to to get the level (use -1 to start from the beginning). + Number of samples (not bytes!) to use (startIndex + length must be less than the buffer size, use -1 to scan the whole buffer size). + If successful, the level of the left channel is returned in the low Dword (low 32-bits), and the level of the right channel is returned in the high Dword (high 32-bits). + Each Dword (32-bit) carries the maximum peak level value in the high word (high 16-bit) and the the minimum peak level value in the low word (low 16-bit). + If the channel is mono, then the low Dword is duplicated in the high Dword. + + Structure of one element (long = 64-bit): + + | 64-bit | + | right | left | + |max.peak|min.peak|max.peak|min.peak| + + + Each peak level ranges linearly from -32768 to 0 (silent) to +32767. + + + + + Equivalent to , but with individual offset and length. + + The buffer pointer to the sample data (e.g. as obtained in a ). + The number of channels to use (1=mono, 2=stereo). In case of mono the left and right channel will contain the same value. + The bytes per sample (or bitwidth) - which can be either 1, 2 or 4 bytes per sample or 8, 16 or 32 bits per sample. + The starting index (sample offset, not byte offset!) within the buffer from where to to get the level (use -1 to start from the beginning). + Number of samples (not bytes!) to use (startIndex + length must be less than the buffer size) - no range check is applied here!. + If successful, the level of the left channel is returned in the low word (low 16-bits), and the level of the right channel is returned in the high word (high 16-bits). If the channel is mono, then the low word is duplicated in the high word. + + Structure of the return value (int = 32-bit): + + | 32-bit | + | right-peak | left-peak | + + + Each peak level ranges linearly from 0 (silent) to +32767 (max). + + + + + Equivalent to , but with individual offset and length. + + The buffer pointer to the sample data (e.g. as obtained in a ). + The number of channels to use (1=mono, 2=stereo). In case of mono the left and right channel will contain the same value. + The bytes per sample (or bitwidth) - which can be either 1, 2 or 4 bytes per sample or 8, 16 or 32 bits per sample. + The starting index (sample offset, not byte offset!) within the buffer from where to to get the level (use -1 to start from the beginning). + Number of samples (not bytes!) to use (startIndex + length must be less than the buffer size) - no range check is applied here!. + If successful, the level of the left channel is returned in the low Dword (low 32-bits), and the level of the right channel is returned in the high Dword (high 32-bits). + Each Dword (32-bit) carries the maximum peak level value in the high word (high 16-bit) and the the minimum peak level value in the low word (low 16-bit). + If the channel is mono, then the low Dword is duplicated in the high Dword. + + Structure of one element (long = 64-bit): + + | 64-bit | + | right | left | + |max.peak|min.peak|max.peak|min.peak| + + + Each peak level ranges linearly from -32768 to 0 (silent) to +32767. + + + + + Decodes all the available data of the given channel right away. + + The channel handle who's channel data should be decoded (should typically be a decoding channel). + , if the channel should be freed (via ) when all the data has been decoded. + The total number of bytes actually decoded. + Internally will be called in a loop as long as the channel is active (BASS_ACTIVE_PLAYING). + This method might be useful, if you want to quickly decode all the data of the channel to e.g. feed it through a DSP. + When using with a mixer channel () make sure to use the flag, since otherwise the mixer channel would never end. + + + + + Detects the cue-in and -out points of a given audio file. + + The audio file to analyze. + The block-size in seconds which will be used to scan the file (between 0.1 and 30 seconds). + Returns the cue-in position in seconds according to . + Returns the cue-out position in seconds according to . + The threshold in dB to be used to detect the . + The threshold in dB to be used to detect the . + Position adjustment flag. 0=no adjustment, 1=move to zero-crossing sample to avoid clicks, 2=move to quiter sample (threshold/2) to avoid clicks. + on success - else . + If is set to 1 the zero-crossing determination will only be performed within the last analyzed . + + + + Detects the cue-in and -out points of a given decoding stream. + + The decoding stream to analyze (should be created with the BASS_STREAM_PRESCAN flag). + The block-size in seconds which will be used to scan the file (between 0.1 and 30 seconds). + Returns the cue-in position in seconds according to . + Returns the cue-out position in seconds according to . + The threshold in dB to be used to detect the . + The threshold in dB to be used to detect the . + Position adjustment flag. 0=no adjustment, 1=move to zero-crossing sample to avoid clicks, 2=move to quiter sample (threshold/2) to avoid clicks. + on success - else (Note: must be a decoding stream and can not be 0). + If is set to 1 the zero-crossing determination will only be performed within the last analyzed . + + + + Finds the next position with a certain volume level. + + The decoding stream to analyze (should be created with the BASS_STREAM_PRESCAN flag). + The block-size in seconds which will be used to scan the file (between 0.1 and 30 seconds). + The position in seconds where to start the search. + The threshold in dB (e.g. -12.0dB) which should be searched. + Search forward () or backward (). + If set to the returned position will be adjusted to the next resp. previous zero crossing in order to avoid clicks. + The position with the respective volume level (if the level could not be detected, then startpos will be returned). + As this method calls internally the current position of the might be changed. + So if you need to preserve this position you must remember it before calling this method and set it afterwards yourself (via and ). + + + + Determines a gain factor (normalization), so that the maximum peak level of the stream will be at 0 dB. + + The audio file to analyze. + The block-size in seconds which will be used to scan the file (between 0.1 and 30 seconds). + The position (in seconds) where to start the calculation (between 0 and file duration, or -1 to scan from the beginning). + The position (in seconds) til where to perform the calculation (between 0 and file duration, or -1 to scan til the end; must be bigger than startpos). + Returns the maximum peak level as a float value between 0.0 (silence) and 1.0 (0dB). + The gain factor as a float value (or -1 on error) - a value of 1 means no amplification. + + You might use the gain factor as a multiplier to the sample data to apply a volume adjustment, so that the maximum peak level of the audio samples is at 0 dB. + + + + + DMA (kernel32.dll) - The CopyMemory function copies a block of memory from one location to another. + + Pointer to the starting address of the copied block's destination. + Pointer to the starting address of the block of memory to copy. + Size of the block of memory to copy, in bytes. + If the source and destination blocks overlap, the results are undefined. For overlapped blocks, use the function. + CAUTION: This method makes a direct call to the windows kernel.dll - you can crash everything when using it in a wrong way! + + + + + DMA (kernel32.dll) - The MoveMemory function moves a block of memory from one location to another. + + Pointer to the starting address of the move destination. + Pointer to the starting address of the block of memory to be moved. + Size of the block of memory to move, in bytes. + The source and destination blocks may overlap. + CAUTION: This method makes a direct call to the windows kernel.dll - you can crash everything when using it in a wrong way! + + + + + DMA (kernel32.dll) - The FillMemory macro fills a block of memory with a specified value. + + Pointer to the starting address of the block of memory to fill. + Size of the block of memory to fill, in bytes. This value must be less than the size of the Destination buffer. + Byte value with which to fill the memory block. + + CAUTION: This method makes a direct call to the windows kernel.dll - you can crash everything when using it in a wrong way! + + + + + DMA (kernel32.dll) - The ZeroMemory macro fills a block of memory with zeros. + + Pointer to the starting address of the block of memory to fill with zeros. + Size of the block of memory to fill with zeros, in bytes. + + CAUTION: This method makes a direct call to the windows kernel.dll - you can crash everything when using it in a wrong way! + + + + + LIB (kernel32.dll) - Loads a native unmanaged library (dll) into the process of our executable. + + Name and/or path to the executable module (either a .dll or .exe file). The name specified is the file name of the module and is not related to the name stored in the library module itself. + If the string does not specify a path, the function uses a standard search strategy to find the file + + If the function succeeds, the return value is a handle to the module. If the function fails, the return value is 0. + This can be used for late bound explicit linking. + If fileName does not include a path and there is more than one loaded module with the same base name and extension, the function returns a handle to the module that was loaded first. + If no file name extension is specified in the fileName parameter, the default library extension .dll is appended. However, the file name string can include a trailing point character (.) to indicate that the module name has no extension. + When no path is specified, the function searches for loaded modules whose base name matches the base name of the module to be loaded. If the name matches, the load succeeds. Otherwise, the function searches for the file. + The first directory searched is the one directory containing the image file used to create the calling process. + + A module loaded via LIBLoadLibrary should be released using the method when it is not needed anymore. + + + + + This function decrements the reference count of the loaded dynamic-link library (DLL) loaded via . + When the reference count reaches zero, the module is unmapped from the address space of the calling process and the handle is no longer valid. + + Handle to the loaded DLL module. The returns this handle. + If the function succeeds, the return value is . If the function fails, the return value is . + Each process maintains a reference count for each loaded library module. This reference count is incremented each time is called and is decremented each time is called. + + + + For internal use only! Will load a given dll into memory. + + The name and/or path of the module (dll) to load. + The handle where to store the returned module handle when loaded. + on success, else . + + + + For internal use only! Will unload a dll by handle. + + The module handle to unload. + on success, else . + + + + Returns , if running in a 64-bit environment - else false (32-bit). + + + + + Implements a secure Timer, which raises an event in defined intervals. + + This timer implementation is based on the , but is optimized to be used in multi-threading environments as well as UI threads. + This Timer uses a event handler which will be raised every milliseconds once the method was called and the timer is activated. + This implementation ensures, that the event will be executed in the main thread the subscriber executes in! + So when subscribing to this event from a UI thread, the specified event delegate will also be called in that UI thread. + Use the method to deactivate the Timer. + You might change the at any time. If the Timer has already been activated, this will also take immediate effect (the next event will be raised after the new interval value). + + + + + Creates a new Timer instance using a default interval of 50ms. + + The timer will not be activated automatically. Call to activate the timer. + + + + Creates a new Timer instance using the given interval. + + The interval in milliseconds at which the event should be raised. + The timer will not be activated automatically. Call to activate the timer. + + + + Implement IDisposable. + + Do not make this method virtual. A derived class should not be able to override this method. + + + + Finalization code. + + This destructor will run only if the Dispose method does not get called. + It gives your base class the opportunity to finalize. Do not provide destructors in types derived from this class. + + + + Activates (starts) the Timer. + + After activating the Timer every milliseconds a event will be raised. + Calling this method on an already active timer will have no effect. + + + + + Deativates (stops) the Timer. + + After deactivating the Timer no more events will be raised. + + + + Event handler used to notify that the timer has elapsed. + + This event will be raised, if the Timer has been started (see ) and the has been elapsed. + Note: This implementation ensures, that the event will be executed in the main thread the subscriber executes in! + So when subscribing to this event from UI thread, the specified event delegate will also be called in that UI thread. + + + + + Gets or Sets the number of milliseconds between two events. + + To get the interval in seconds you need to divide this number by 1000. + The event will only be raised, if the Timer is active (see ). + Specify 0 (zero) or a nagative value to inactivate the periodic signalling of the event - however in this case the Timer remain activated. + + + + + Gets or Sets if the Timer is currently active. + + Returns , if the Timer is active. + Setting this property will have the same effect as calling respectivly . + + + + + Implements a fast and generic circular ring buffer (FiFo). + + This implementation uses an internal byte array as a buffer and can be used in multi-threading environments, since all members are thread-safe. + The default size of the ring buffer is 2 seconds (when using it with 44.1kHz, 16-bit stereo sample data). + This class supports multiple readers using the ring buffer (default is 1). Use the property to set the maximum number of parallel readers accessing the ring buffer. + The ring buffer is not a dynamic buffer, meaning it has a fixed size once created. However, the ring buffer size might be increased at any time through the method, even if you should avoid this for performance reasons. + Use the method to add sample data to the ring buffer. And use the method to retrieve sample data from the ring buffer. + This class might be useful for full-duplex monitoring of a recording streams or in order to clone existing streams. + In order to reduce latency, you might probably want to minimize the recording update period (see . + You'll probably also want to reduce the update period (BASS_CONFIG_UPDATEPERIOD) and buffer length (BASS_CONFIG_BUFFER), to reduce output latency (see ). + + + BASS Recording with full-duplex monitoring: + + private RECORDPROC _myRecProc; // make it global, so that the GC can not remove it + private int _recHandle = 0; + // The buffer: 44.1kHz, 16-bit, stereo (like we record!) + private BASSBuffer _monBuffer = new BASSBuffer(2f, 44100, 2, 16); + private int _monStream = 0; + private STREAMPROC _monProc = null; + ... + // enable lower latency settings (optional) + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 20); + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_BUFFER, 100); + // start recording with 20ms update period + _myRecProc = new RECORDPROC(MyRecording); + _recHandle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_DEFAULT, 20, _myRecProc, IntPtr.Zero); + // setup the full-duplex monitoring + _monProc = new STREAMPROC(MonitoringStream); + _monStream = Bass.BASS_StreamCreate(44100, 2, 0, _monProc, IntPtr.Zero); // user = reader# + Bass.BASS_ChannelPlay(_monStream, false); + + private bool MyRecording(int handle, IntPtr buffer, int length, IntPtr user) + { + monBuffer.Write(buffer, length); + } + + private int MonitoringStream(int handle, IntPtr buffer, int length, IntPtr user) + { + return monBuffer.Read(buffer, length, user.ToInt32()); + } + + + Private _myRecProc As RECORDPROC ' make it global, so that the GC can not remove it + Private _recHandle As Integer = 0 + ' The buffer: 44.1kHz, 16-bit, stereo (like we record!) + Private _monBuffer As New BASSBuffer(2F, 44100, 2, 16) + Private _monStream As Integer = 0 + Private _monProc As STREAMPROC = Nothing + ... + ' enable lower latency settings (optional) + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 20) + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_BUFFER, 100) + ' start recording with 20ms update period + _myRecProc = New RECORDPROC(MyRecording) + _recHandle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_DEFAULT, 20, _myRecProc, IntPtr.Zero) + ' setup the full-duplex monitoring + _monProc = New STREAMPROC(AddressOf MonitoringStream) + _monStream = Bass.BASS_StreamCreate(44100, 2, 0, _monProc, IntPtr.Zero) ' user = reader# + Bass.BASS_ChannelPlay(_monStream, False) + + Private Function MyRecording(handle As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Boolean + monBuffer.Write(buffer, length) + End Function + + Private Function MonitoringStream(handle As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Integer + Return monBuffer.Read(buffer, length, user.ToInt32()) + End Function + + + + + + Default Constructor using the default buffer size. + + The default size of the buffer is 2 seconds (when using it with 44.1kHz, 16-bit stereo sample data). + + + + Creates an instance of the ring buffer with a size acconding to the given parameters. + + The length of the buffer in seconds (e.g. 2.0 for 2 seconds or 0.2 for 200ms). + The samplerate in Hz to use. + The number of channels to use. + Bytes per Sample (1 = 8-bit, 2 = 16-bit or 4 = 32-bit sample data, but you might also use 8, 16 or 32 here directly). + The internal buffer size is calculated accordingly to the above parameters, rounded to the next sample mathich the given bytes per sample. + The buffer size is calculated as: seconds * samplerate * chans * bps + + + + + Implement IDisposable. + + + + + Finalization code. + + This destructor will run only if the Dispose method does not get called. + It gives your base class the opportunity to finalize. Do not provide destructors in types derived from this class. + + + + Clears the ring buffer (zeros all elements) and resets all read and write pointers. + + + + + Resizes (enlarges) the ring buffer by the given factor. + + The factor to use for resizing (the buffer size is multiplied by this factor). Must be greater than 1.0. + Shrinking the buffer size is not allowed. + + + + Returns the number of bytes available in the ring buffer for writing until an overflow of the read pointer will happen. + + The zero-based index of the reader to use (0=first reader) or -1 to get the smallest available space for all readers. + In order to convert the available space in the buffer to number of samples, simply devide the result by the bytes per sample + (e.g. if the result is 56780 and you are using the buffer with 16-bit stereo sample data, the number of sample are 56780/2 = 28390 samples or 14195 stereo pairs). + Note, that there is never a real physical write limitation, since writing to the buffer always has priority. + Meaning if there is not sufficient space left between the write pointer position and the last read pointer position, this fact is simply ignored. The data will be written anyhow. + However, this will result in an overflow, so that the next read operation will only have the overflown sample data available - resulting in a gap in the sound. + + Returns the number of bytes available in the ring buffer for writing until an overflow of the read pointer will happen (space between the current write pointer position and the read pointer position). + + + + Returns the number of bytes available in the ring buffer for reading. + + The zero-based index of the reader to use (0=first reader) or -1 to get the biggest number of bytes for all readers. + In order to convert the bytes in the buffer to number of samples, simply devide the result by the bytes per sample + (e.g. if the result is 56780 and you are using the buffer with 16-bit stereo sample data, the number of sample are 56780/2 = 28390 samples or 14195 stereo pairs). + The number of bytes available in the ring buffer for reading (between the current read pointer position and the write pointer position). + + + + Writes (add) the given number of sample data to the ring buffer. + + The pointer to the buffer containing the sample data to write to the ring buffer (e.g. as provided by a , etc. or even by ). + The number of BYTES to write to the ring buffer (from the ). + The number of bytes actually written to the ring buffer. + + + + Writes (add) the given number of sample data to the ring buffer. + + The byte array containing the sample data to write to the ring buffer. + The number of BYTES to write to the ring buffer (from the ). + The number of bytes actually written to the ring buffer. + + + + Reads (removes) the given number of sample data from the ring buffer. + + The pointer to the buffer where the read sample data should be written to (e.g. as provided by a ). + The number of BYTES to read from the ring buffer (which will be written to the ). + The zero-based index of the reader to use (0=first reader). + The number of bytes actually read from the ring buffer (which be be less than requested). + + + + Reads (removes) the given number of sample data from the ring buffer. + + The byte array where the read sample data should be written to (must be initialized and large enough to keep the data). + The number of BYTES to read from the ring buffer (which will be written to the ). + The zero-based index of the reader to use (0=first reader). + The number of bytes actually read from the ring buffer (which might be less than requested). + + + + Gets the total length in bytes of the ring buffer. + + + + + Gets the Bytes per sample used with the ring buffer (1=8-bit, 2=16-bit default, 4=32-bit). + + + + + Gets the sample rate in Hz used with the ring buffer (default is 44100 Hz). + + + + + Gets the number of channels used with the ring buffer (1=mono, 2=stereo default, etc). + + + + + Gets or Sets the number of parallel Readers which can be used with the ring buffer. + + + + + BASS.NET API wrapper for BASS_SPX.DLL + Requires: bass_sfx.dll - Winamp and Sonique Visualization plugins support Add-On - available @ www.un4seen.com. + + + BassSfx is an extention to the BASS audio library, providing a set of functions for rendering Sonique Visualization plugins or Winamp visualization plugins on a provided device context (hDC). + + + + + Current BASS_SFX version (without minor revision). + + + + + NOT used - all members are static! + + + + + Retrieves the version number of the BASS_SFX.DLL that is loaded. + + The BASS_SFX version. For example, 0x02040103 (hex), would be version 2.4.1.3. + There is no guarantee that a previous or future version of BASS_SFX supports all the BASS_SFX functions that you are using, so you should always use this function to make sure the correct version is loaded. + It is safe to assume that future minor revisions (indicated in the LOWORD) will be fully compatible. + You might use the global constant to check the major revision. + Note: Calling this method will also automatically load the library into memory. + + + Checking the major version only: + + if ( Utils.HighWord(BassSfx.BASS_SFX_GetVersion()) != BassSfx.BASSSFXVERSION ) + { + MessageBox.Show(this, "Wrong BassSfx Version!"); + } + + + If Utils.HighWord(BassSfx.BASS_SFX_GetVersion()) <> BassSfx.BASSSFXVERSION Then + MessageBox.Show(Me, "Wrong BassSfx Version!") + End If + + Checking for full version "2.4.1.3": + + if (BassSfx.BASS_SFX_GetVersion() < Utils.MakeLong(0x0103, 0x0204)) + { + MessageBox.Show(this, "Wrong BassSfx Version!"); + } + + + If BassSfx.BASS_SFX_GetVersion() < Utils.MakeLong(&H103, &H204) Then + MessageBox.Show(Me, "Wrong BassSfx Version!") + End If + + + + + + Retrieves the version of the BASS_SFX.DLL that is loaded. + + The number of components to use. The fieldCount ranges from 1 to 4 (major.minor.build.revision). + The BASS_SFX version (major.minor.build.revision). + There is no guarantee that a previous or future version of BASS_SFX supports all the BASS_SFX functions that you are using, so you should always use this function to make sure the correct version is loaded. + It is safe to assume that future minor revisions (indicated in the LOWORD) will be fully compatible. + Note: Calling this method will also automatically load the library into memory. + + + + Version expectedVersion = new Version(2, 4); + if (BassSfx.BASS_SFX_GetVersion(2) < expectedVersion) + { + MessageBox.Show( this, "Wrong BassSfx Version!" ); + } + + + Dim expectedVersion As New Version(2, 4) + If BassSfx.BASS_SFX_GetVersion(2) < expectedVersion Then + MessageBox.Show(Me, "Wrong BassSfx Version!") + End If + + + + + + Initialize the SFX library. This will initialize the library for use. + + Your application instance handle (i.e. Process.GetCurrentProcess().Handle). + Your main windows form handle. + If an error occurred then is returned, else is returned. + Call this method prior to any other BASS_SFX methods. + Call to free all resources and before your program exits. + + + ERROR CODEDescription + BASS_SFX_ERROR_ALREADYAlready initialized. + BASS_SFX_ERROR_MEMThere is insufficient memory. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + BassSfx.BASS_SFX_Init(); + + + BassSfx.BASS_SFX_Init() + + + + + + Frees all resources used by SFX. + + If successful, then is returned, else is returned. + This function should be called before your program exits. + + + + Creates a plugin object for use in the SFX. + + The filename and path of the plugin to load. + The handle of the window where the plugin is to be rendered. + The initial width for the plugins rendering window. + The initial height for the plugins rendering window. + Any combination of these flags (see ): + + BASS_SFX_SONIQUE_OPENGLRender sonique plugins using OpenGL. + BASS_SFX_SONIQUE_OPENGL_DOUBLEBUFFERUse OpenGL double buffering with sonique plugins. + + + If successful, the new SFX plugin handle is returned, else 0 is returned. + + Once you create a plugin using this function you can perform a number of different function calls on it. + The and parameters are only useful for BassBox, WMP, and Sonique plugins. + Winamp ignores these parameters so you can just pass in 0 for winamp plugins. + Windows Media Player plugins can be created using the full path to a dll file or by using the CLSID GUID from the registry. + Mainly you might use the , or methods. + Note: This method uses the unicode overload of the native API (BASS_SFX_PluginCreateW). + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_FILEOPENCan't open the plugin file. + BASS_SFX_ERROR_FORMATUnsupported plugin format. + BASS_SFX_ERROR_GUIDCan't open WMP plugin using specified GUID. + BASS_SFX_ERROR_MEMThere is insufficient memory. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + // create a plugin object + int sfx = BassSfx.BASS_SFX_PluginCreate("corona.svp", pictureBox1.Handle, pictureBox1.Width, pictureBox1.Height, BASSSFXFlag.BASS_SFX_DEFAULT); + if (sfx != 0) + { + // loaded file successfully + BASS_SFX_PluginStart(sfx); + } + + + ' create a plugin object + Dim sfx As Integer = BassSfx.BASS_SFX_PluginCreate("corona.svp", pictureBox1.Handle, pictureBox1.Width, pictureBox1.Height, BASSSFXFlag.BASS_SFX_DEFAULT) + If sfx <> 0 Then + ' loaded file successfully + BASS_SFX_PluginStart(sfx); + End If + + + + + + Get the type of visual plugin loaded. + + The SFX plugin handle (as obtained by ). + If successful, either , , or is returned, else is returned. + + You must have created a plugin object using before you can use this function. + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_HANDLEInvalid SFX handle. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + if (BassSfx.BASS_SFX_PluginGetType(sfx) == BASSSFXPlugin.BASS_SFX_WINAMP) + { + // a winamp visual plugin was loaded + } + else if (BassSfx.BASS_SFX_PluginGetType(sfx) == BASSSFXPlugin.BASS_SFX_SONIQUE) + { + // a sonique visual plugin was loaded + } + else if (BassSfx.BASS_SFX_PluginGetType(sfx) == BASSSFXPlugin.BASS_SFX_WMP) + { + // a WMP visual plugin was loaded + } + else if (BassSfx.BASS_SFX_PluginGetType(sfx) == BASSSFXPlugin.BASS_SFX_BBP) + { + // a BassBox visual plugin was loaded + } + else + { + // we have either loaded nothing or an unsupported plugin + } + + + If BassSfx.BASS_SFX_PluginGetType(sfx) = BASSSFXPlugin.BASS_SFX_WINAMP Then + ' a winamp visual plugin was loaded + ElseIf BassSfx.BASS_SFX_PluginGetType(sfx) = BASSSFXPlugin.BASS_SFX_SONIQUE Then + ' a sonique visual plugin was loaded + ElseIf BassSfx.BASS_SFX_PluginGetType(sfx) = BASSSFXPlugin.BASS_SFX_WMP Then + ' a WMP visual plugin was loaded + ElseIf BassSfx.BASS_SFX_PluginGetType(sfx) = BASSSFXPlugin.BASS_SFX_BBP Then + ' a BassBox visual plugin was loaded + Else + ' we have either loaded nothing or an unsupported plugin + End If + + + + + + Sets a BASS channel on a SFX plugin. + + The SFX plugin handle (as obtained by ). + The BASS channel to render, can be a HSTREAM or HMUSIC handle. + If successful, then is returned, else is returned. + + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_HANDLEInvalid SFX or channel handle. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + // create a BASS channel + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_DEFAULT); + // create a plugin object + int sfx = BASS_SFX_PluginCreate("corona.svp", pictureBox1.Handle, pictureBox1.Width, pictureBox1.Height, BASSSFXFlag.BASS_SFX_DEFAULT); + if (sfx != 0 && stream != 0) + { + // loaded file successfully + if (BASS_SFX_PluginStart(sfx)) + BASS_SFX_PluginSetStream(sfx, stream); + } + + + ' create a BASS channel + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_DEFAULT); + ' create a plugin object + Dim sfx As Integer = BassSfx.BASS_SFX_PluginCreate("corona.svp", pictureBox1.Handle, pictureBox1.Width, pictureBox1.Height, BASSSFXFlag.BASS_SFX_DEFAULT) + If sfx <> 0 AndAlso stream <> 0 Then + ' loaded file successfully + If BASS_SFX_PluginStart(sfx) Then + BASS_SFX_PluginSetStream(sfx, stream) + End If + End If + + + + + + Starts a visual plugin. + + The SFX plugin handle (as obtained by ). + If successful, then is returned, else is returned. + Use to stop a SFX plugin. + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_HANDLEInvalid SFX handle. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + // create a BASS channel + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_DEFAULT); + // create a plugin object + int sfx = BassSfx.BASS_SFX_PluginCreate("corona.svp", pictureBox1.Handle, pictureBox1.Width, pictureBox1.Height, BASSSFXFlag.BASS_SFX_DEFAULT); + if (sfx != 0 && stream != 0) + { + // loaded file successfully + if (BASS_SFX_PluginStart(sfx)) + BASS_SFX_PluginSetStream(sfx, stream); + } + + + ' create a BASS channel + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_DEFAULT); + ' create a plugin object + Dim sfx As Integer = BassSfx.BASS_SFX_PluginCreate("corona.svp", 320, 240) + If sfx <> 0 AndAlso stream <> 0 Then + ' loaded file successfully + If BASS_SFX_PluginStart(sfx) Then + BASS_SFX_PluginSetStream(sfx, stream) + End If + End If + + + + + + Stops a visual plugin. + + The SFX plugin handle (as obtained by ). + If successful, then is returned, else is returned. + Use to start a SFX plugin. + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_HANDLEInvalid SFX handle. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Free a sonique visual plugin and resources from memory. + + The SFX plugin handle (as obtained by ). + If successful, then is returned, else is returned. + It is very important to call this function after you are done using a plugin to avoid memory leaks. + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_HANDLEInvalid SFX handle. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + + + + + + + + + Gets the name of a loaded SFX plugin. + + The SFX plugin handle (as obtained by ). + If successful, the name of the plugin is returned, else is returned. + + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_HANDLEInvalid SFX handle. + BASS_SFX_ERROR_MEMMemory error. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + // create a plugin object + int sfx = BassSfx.BASS_SFX_PluginCreate("corona.svp", pictureBox1.Handle, pictureBox1.Width, pictureBox1.Height, BASSSFXFlag.BASS_SFX_DEFAULT); + if (sfx != 0) + { + // get the plugin name + Console.WriteLine(BassSfx.BASS_SFX_PluginGetName(sfx)); + } + + + ' create a plugin object + Dim sfx As Integer = BassSfx.BASS_SFX_PluginCreate("corona.svp", pictureBox1.Handle, pictureBox1.Width, pictureBox1.Height, BASSSFXFlag.BASS_SFX_DEFAULT) + If sfx <> 0 Then + ' get the plugin name + Console.WriteLine(BassSfx.BASS_SFX_PluginGetName(sfx)); + End If + + + + + + Shows the configuration dialog window for the SFX plugin (Winamp only). + + The SFX plugin handle (as obtained by ). + If successful, then is returned, else is returned. + + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_HANDLEInvalid SFX handle. + BASS_SFX_ERROR_MEMMemory error. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Gets the number of modules available in the visual plugin. + + The SFX plugin handle (as obtained by ). + If successful, the number of modules is returned, else -1 is returned. + + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_HANDLEInvalid SFX handle. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + + + + + + + + + + Returns the name of a certain module of a loaded visual plugin. + + The SFX plugin handle (as obtained by ). + The module number to get the name from (the first module is 0). + The name of the module on success or on error (or if no module with that number exists). + Visual plugins might provide multiple independent modules. You might get the number of available modules with . + However, you can only start/activate one module at a time for a certain visual plugin. + Note: Sonique plugins only ever have 1 module. Winamp plugins can have multiple modules. So this call is really only useful for Winamp. + You can use this method in a setup dialog to list all the available modules of a visual plugin. + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_HANDLEInvalid SFX handle. + BASS_SFX_ERROR_MEMMemory error. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + string name; + for (int n=0; (name = BassSfx.BASS_SFX_PluginModuleGetName(sfx, n)) != null; n++) + { + Console.WriteLine(name); + } + + + Dim n As Integer = 0 + Dim name As String = "" + While Not (name Is Nothing) + name = BassSfx.BASS_SFX_PluginModuleGetName(sfx, n) + n += 1 + If Not (name Is Nothing) Then + Console.WriteLine(name) + End If + End While + + + + + + Sets the active module for a visual plugin. + + The SFX plugin handle (as obtained by ). + The module number to set active (the first module is 0). + If successful, then is returned, else is returned. + Visual plugins might provide multiple independent modules. You might get the number of available modules with . + However, you can only start/activate one module at a time for a certain visual plugin. + Note: Sonique plugins only ever have 1 module. Winamp plugins can have multiple modules. So this call is really only useful for Winamp. + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_HANDLEInvalid SFX handle or invalid module index. + BASS_SFX_ERROR_MEMMemory error. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Gets the active module for a visual plugin. + + The SFX plugin handle (as obtained by ). + If successful, the active module (zero based index) is returned, else -1 is returned. + Visual plugins might provide multiple independent modules. You might get the number of available modules with . + However, you can only start/activate one module at a time for a certain visual plugin. + Note: Sonique plugins only ever have 1 module. Winamp plugins can have multiple modules. So this call is really only useful for Winamp. + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_HANDLEInvalid SFX handle. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Renders a Sonique, BassBox or Windows Media Player visual plugin to a device context. + + The SFX plugin handle (as obtained by ). + The BASS channel to render, can be a HSTREAM or HMUSIC handle. + The device context handle of the control to which you want to render the plugin. + If successful, then is returned, else is returned. + + Only for use with Sonique, BassBox or Windows Media Player plugins. + A device context handle (hDC) can be obtained using the class. + E.g. you might get a device context for any control by calling the method. + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_HANDLEInvalid SFX handle. + BASS_SFX_ERROR_MEMMemory error. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Calls the 'clicked' function of a Sonique visual plugin. + + The SFX plugin handle (as obtained by ). + The x coordinate of the click relative to the top left of your visual window. + The y coordinate of the click relative to the top left of your visual window. + If successful, then is returned, else is returned. + + This function is only valid for Sonique Visualization plugins. + You must have created a plugin object using before you can use this function. + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_HANDLEInvalid SFX handle. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Resizes a visual plugin. + + The SFX plugin handle (as obtained by ). + The new width of your visual window. + The new height of your visual window. + If successful, then is returned, else is returned. + + You must have created a plugin object using before you can use this function. + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_HANDLEInvalid SFX handle. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Resizes and moves a visual plugin. + + The SFX plugin handle (as obtained by ). + The new left location of your visual window. + The new top location of your visual window. + The new width of your visual window. + The new height of your visual window. + If successful, then is returned, else is returned. + + You must have created a plugin object using before you can use this function. + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_HANDLEInvalid SFX handle. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Modifies and/or retrieves a plugin's flags. + + The SFX plugin handle (as obtained by ). + Any combination of these flags (see ): + + BASS_SFX_SONIQUE_OPENGLRender sonique plugins using OpenGL. + BASS_SFX_SONIQUE_OPENGL_DOUBLEBUFFERUse OpenGL double buffering with sonique plugins. + + + The flags (as above) to modify. Flags that are not included in this are left as they are, so it can be set to 0 () in order to just retrieve the current flags. + If successful, the plugin's updated flags are returned, else -1 is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_HANDLEInvalid SFX handle. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + // set OpenGL flag: + BassSfx.BASS_SFX_PluginFlags(hsfx, BASSSFXFlag.BASS_SFX_SONIQUE_OPENGL, BASSSFXFlag.BASS_SFX_SONIQUE_OPENGL); + + // remove OpenGL flag: + BassSfx.BASS_SFX_PluginFlags(hsfx, BASSSFXFlag.BASS_SFX_DEFAULT, BASSSFXFlag.BASS_SFX_SONIQUE_OPENGL); + + + ' set openGL flag: + BassSfx.BASS_SFX_PluginFlags(hsfx, BASSSFXFlag.BASS_SFX_SONIQUE_OPENGL, BASSSFXFlag.BASS_SFX_SONIQUE_OPENGL) + + ' remove OpenGL flag: + BassSfx.BASS_SFX_PluginFlags(hsfx, BASSSFXFlag.BASS_SFX_DEFAULT, BASSSFXFlag.BASS_SFX_SONIQUE_OPENGL) + + + + + + + + + + + + + + Retrieves information on a registered windows media player plugin. + + The plugin to get the information of... 0 = first. + instance where to store the plugin information at. + If successful, then is returned, else is returned. + + This function can be used to enumerate all the available windows media player visualization plugins that are registered on the system. + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_MEMMemory error. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + Getting the plugin info: + + BASS_SFX_PLUGININFO info = new BASS_SFX_PLUGININFO(); + BassSfx.BASS_SFX_WMP_GetPlugin(0, info); + Console.WriteLine( info.ToString() ); + + + Dim info As New BASS_SFX_PLUGININFO() + BassSfx.BASS_SFX_WMP_GetPlugin(0, info) + Console.WriteLine(info.ToString()) + + + + + + Retrieves information on a registered windows media player plugin. + + The plugin to get the information of... 0 = first. + An instance of the class on success - else . + + This function can be used to enumerate all the available windows media player visualization plugins that are registered on the system. + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_MEMMemory error. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + Getting the plugin info: + + BASS_SFX_PLUGININFO info = BassSfx.BASS_SFX_WMP_GetPlugin(0); + Console.WriteLine( info.ToString() ); + + + Dim info As BASS_SFX_PLUGININFO = Bass.BASS_SFX_WMP_GetPlugin(0) + Console.WriteLine(info.ToString()) + + + + + + Returns the total number of WMP plugins currently available for use. + + Number of available windows media plugins. + Uses internally. + + + ERROR CODEDescription + BASS_SFX_ERROR_INIT has not been successfully called. + BASS_SFX_ERROR_MEMMemory error. + BASS_SFX_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Retrieves the error code for the most recent BASS_SFX function call. + + If no error occured during the last BASS_SFX function call then BASS_SFX_OK is returned, else one of the values is returned. + See the function description for an explanation of what the error code means. + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + BASS_SFX error codes as returned by (int). + + + + + All is OK. + + + + + Memory error. + + + + + Can't open the file. + + + + + Invalid handle. + + + + + Already initialized. + + + + + Unsupported plugin format. + + + + + has not been successfully called. + + + + + Can't open WMP plugin using specified GUID. + + + + + Some other mystery problem. + + + + + Flag which identifies the type/kind of the visual plugin. + + + + + Sonique visual plugin. + + + + + Winamp visual plugin. + + + + + Windows Media Player visual plugin. + + + + + BassBox visual plugin. + + + + + An unknown plugin type (not supported). + + + + + Visual plugin's flags, to be used with . + + + + + Default flags (use GDI rendering). + + + + + Render sonique plugins using OpenGL. + + + + + Use OpenGL double buffering. + + + + + Used with to retrieve information on a registered Windows Media Player plugin. + + + This function can be used to enumerate all the available windows media player visualization plugins that are registered on the system. + + + + + The description of the plugin. + + + + + The classid of the windows media player plugin that can be used with to create the plugin for use in BASS_SFX. + + + + + Default constructor. + + + + + The description of the plugin. + + The description of the plugin. + + + + BASS.NET API wrapper for BASS_AAC.DLL + Requires: bass_aac.dll - AAC and MP4 Audio Codec (AAC) Add-On - available @ www.un4seen.com. + + + BASS_AAC is an extension to the BASS audio library, enabling the playback of AAC and MP4 files and streams. + Advanced Audio Coding (AAC) is a wideband audio coding algorithm that exploits two primary coding strategies to dramatically reduce the amount of data needed to convey high-quality digital audio. + First, signal components that are "perceptually irrelevant" and can be discarded without a perceived loss of audio quality are removed. Next, redundancies in the coded audio signal are eliminated. + Efficient audio compression is achieved by a variety of perceptual audio coding and data compression tools, which are combined in the MPEG-4 AAC specification. + The AAC and MP4 formats are used in the same way as any of the built-in BASS stream formats. Simply call to load the add-on into BASS and benefit the usage of the standard sample/stream/URL/user functions, or call the /URL/User functions. + More information can be found on www.vialicensing.com. + BASS_AAC is distributed under the GPL (see LICENSE.TXT). + - For commercial use of BASS_AAC, please contact Nero AG at Partner with Nero to implement Nero Digital™ technology. + - AAC is a patented technology. To use it in your software, please obtain a license from Via Licensing at www.vialicensing.com. + + + + + NOT used - all members are static! + + + + + + + + + + + + + + + + Creates a sample stream from a AAC file. + This overload implements UNICODE filenames. The BASS_UNICODE flag will be added automatically, since all .Net strings are always unicode. + + Filename for which a stream should be created. + File offset to begin streaming from. + Data length... 0 = use all data up to the end of the file. + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + + + + + + + + + + + + Creates a sample stream from a AAC memory IntPtr. + This overload implements streaming from memory. + + An unmanaged pointer to the memory location as an IntPtr. + Offset to begin streaming from (unused for memory streams, set to 0). + Data length (needs to be set to the length of the memory streams in bytes which should be played). + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + Creates a sample stream from a AAC file via a user callback function. + + File system to use: see . + Any combination of these flags: see . + The user defined file functions (see ). + User instance data to pass to the callback functions. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + See . + + + + + + + + + + + + + + + + + + + + + + + + + + Creates a sample stream from a AAC file on the internet, optionally receiving the downloaded data in a callback. + + URL of the file to stream. Should begin with "http://" or "ftp://". + File position to start streaming from. This is ignored by some servers, specifically when the file length is unknown. + Any combination of these flags: see . + Callback function to receive the file as it is downloaded... = no callback. + User instance data to pass to the callback function. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + + + + + + + + + + + + Creates a sample stream from a MP4 file. + This overload implements UNICODE filenames. The BASS_UNICODE flag will be added automatically, since all .Net strings are always unicode. + + Filename for which a stream should be created. + File offset to begin streaming from. + Data length... 0 = use all data up to the end of the file. + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + + + + + + + + + + + + Creates a sample stream from a MP4 memory IntPtr. + This overload implements streaming from memory. + + An unmanaged pointer to the memory location as an IntPtr. + Offset to begin streaming from (unused for memory streams, set to 0). + Data length (needs to be set to the length of the memory streams in bytes which should be played). + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + Creates a sample stream from a MP4 file via user callback functions. + + File system to use: see . + Any combination of these flags: see . + The user defined file functions (see ). + User instance data to pass to the callback functions. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + See . + + + + Supported file extensions of the bass_aac.dll + + + + + Supported file format name of the bass_aac.dll + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + The disadvantage of this method is, that the standard plugin support for is not working - so you would need to use the native add-on methods! + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + BASS.NET Splash Screen. + + + + + BASS.NET Splash Screen constructor. + + + + + .NET API wrapper for BASSWASAPI.DLL + Requires: basswasapi.dll - Windows Audio Session API driver library - available @ www.un4seen.com. + + + BASSWASAPI is basically a wrapper for Windows Audio Session API drivers, with the addition of channel joining, format conversion and resampling. + BASSWASAPI requires a soundcard with a Windows Session API drivers installed (Vista or above). It also makes use of SSE2 and 3DNow optimizations, but is fully functional without them. + BASS is not required by BASSWASAPI, but BASS can of course be used to decode, apply DSP/FX, etc. + + + + + Current BASSWASAPI version (without minor revision). + + + + + Base static contructor. + + + + + NOT used - all members are static! + + + + + Retrieves the version number of the basswasapi.dll that is loaded. + + The BASSWASAPI version. For example, 0x02040103 (hex), would be version 2.4.1.3. + There is no guarantee that a previous or future version of BASSWASAPI supports all the BASSWASAPI functions that you are using, so you should always use this function to make sure the correct version is loaded. + It is safe to assume that future minor revisions (indicated in the LOWORD) will be fully compatible. + You might use the global constant to check the major revision. + + + Checking the major version only: + + if ( Utils.HighWord(BassWasapi.BASS_WASAPI_GetVersion()) != BassWasapi.BASSWASAPIVERSION ) + { + MessageBox.Show(this, "Wrong BassWasapi Version!"); + } + + + If Utils.HighWord(BassWasapi.BASS_WASAPI_GetVersion()) <> BassWasapi.BASSWASAPIVERSION Then + MessageBox.Show(Me, "Wrong BassWasapi Version!") + End If + + Checking for full version "2.4.1.3": + + if (BassWasapi.BASS_WASAPI_GetVersion() < Utils.MakeLong(0x0103, 0x0204)) + { + MessageBox.Show(this, "Wrong BassWasapi Version!"); + } + + + If BassWasapi.BASS_WASAPI_GetVersion() < Utils.MakeLong(&H103, &H204) Then + MessageBox.Show(Me, "Wrong BassWasapi Version!") + End If + + + + + + Retrieves the version of the basswasapi.dll that is loaded. + + The number of components to use. The fieldCount ranges from 1 to 4 (major.minor.build.revision). + The BASSWASAPI version (major.minor.build.revision). + There is no guarantee that a previous or future version of BASSWASAPI supports all the BASSWASAPI functions that you are using, so you should always use this function to make sure the correct version is loaded. + It is safe to assume that future minor revisions (indicated in the LOWORD) will be fully compatible. + + + Version expectedVersion = new Version(2, 4); + if (BassWasapi.BASS_WASAPI_GetVersion(2) < expectedVersion) + { + MessageBox.Show( this, "Wrong BassWasapi Version!" ); + } + + + Dim expectedVersion As New Version(2, 4) + If BassWasapi.BASS_WASAPI_GetVersion(2) < expectedVersion Then + MessageBox.Show(Me, "Wrong BassWasapi Version!") + End If + + + + + + + + + + + + + + Retrieves information on a Wasapi device (endpoint). + + The device to get the information of... 0 = first. + An instance of the class to store the information at. + If successful, then is returned, else is returned. Use to get the error code. + + This function can be used to enumerate the available Wasapi devices (endpoints) for a setup dialog. + Note: Input (capture) devices can be determined by evaluating the member (which must be either BASS_DEVICE_INPUT or BASS_DEVICE_LOOPBACK). + + + ERROR CODEDescription + BASS_ERROR_WASAPIWASAPI is not available. + BASS_ERROR_DEVICEThe device number specified is invalid. + + + + + List all available endpoints: + + BASS_WASAPI_DEVICEINFO info = new BASS_WASAPI_DEVICEINFO(); + for (int n=0; BassWasapi.BASS_WASAPI_GetDeviceInfo(n, info); n++) + { + Console.WriteLine(info.ToString()); + } + + + Dim n As Integer = 0 + Dim info As New BASS_WASAPI_DEVICEINFO() + While (BassWasapi.BASS_WASAPI_GetDeviceInfo(n, info)) + Console.WriteLine(info.ToString()) + n += 1 + End While + + Or use the method for more convenience. + + + + + Retrieves information on a Wasapi device (endpoint). + + The device to get the information of... 0 = first. + If successful, then an instance of the class is returned, else is returned. Use to get the error code. + + This function can be used to enumerate the available Wasapi devices (endpoints) for a setup dialog. + Note: Input (capture) devices can be determined by evaluating the member (which must be either BASS_DEVICE_INPUT or BASS_DEVICE_LOOPBACK). + + + ERROR CODEDescription + BASS_ERROR_WASAPIWASAPI is not available. + BASS_ERROR_DEVICEThe device number specified is invalid. + + + + + + BASS_WASAPI_DEVICEINFO info; + for (int n = 0; (info = BassWasapi.BASS_WASAPI_GetDeviceInfo(n)) != null; n++) + { + ... + } + + + Dim n As Integer = 0 + Dim info As New BASS_WASAPI_DEVICEINFO() + While Not (info Is Nothing) + info = BassWasapi.BASS_WASAPI_GetDeviceDescription(n) + If Not (info Is Nothing) Then + ... + End If + n += 1 + End While + + Or use the method for more convenience. + + + + + Returns all available Wasapi devices (endpoints). + + An array of elements representing the available Wasapi devices (endpoints). + Uses internally. + This function lists all available endpoits (rendering as well as capturing devices). + Input (capture) devices can be determined by evaluating the member (which must be either BASS_DEVICE_INPUT or BASS_DEVICE_LOOPBACK). + + + + + + Returns the total number of available Wasapi devices (endpoints). + + Number of WASAPI devices (endpoints) available. + Uses internally. + + + + Sets the device to use for subsequent calls in the current thread. + + The device to use... 0 = first device. + If successful, then is returned, else is returned. Use to get the error code. + + Simultaneously using multiple devices is supported in the BASS API via a context switching system; instead of there being an extra "device" parameter in the function calls, the device to be used is set prior to calling the functions. The device setting is local to the current thread, so calling functions with different devices simultaneously in multiple threads is not a problem. + All of the BASSWASAPI functions that do not have their own "device" parameter make use of this device selection. When one of them is called, BASSWASAPI will check the current thread's device setting, and if no device is selected (or the selected device is not initialized), BASSWASAPI will automatically select the lowest device that is initialized. This means that when using a single device, there is no need to use this function; BASSWASAPI will automatically use the device that is initialized. Even if you free the device, and initialize another, BASSWASAPI will automatically switch to the one that is initialized. + + + ERROR CODEDescription + BASS_ERROR_DEVICEThe number specified is invalid. + BASS_ERROR_INITThe device has not been initialized. + + + + + + + Retrieves the Wasapi device setting in the current thread. + + If successful, the device number is returned, else -1 is returned. Use to get the error code. + As in BASS, simultaneously using multiple devices is supported in the BASSWASAPI API via a context switching system - instead of there being an extra "device" parameter in the function calls, the device to be used needs to be set via prior to calling the function. The device setting is local to the current thread, so calling functions with different devices simultaneously in multiple threads is not a problem. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called - there are no initialized devices. + + + + + + + Checks if a particular sample format is supported by a device (endpoint). + + The device to use... 0 = first device, -1 = default device, -2 = default input device. can be used to enumerate the available devices. + The sample rate to check. + The number of channels to check... 1 = mono, 2 = stereo, etc. + Any combination of these flags (see ): + + BASS_WASAPI_SHAREDCheck the device in shared mode. + BASS_WASAPI_EXCLUSIVECheck the device in exclusive mode. + The HIWORD - use Utils.MakeLong(flags,format) - can be used to limit the sample formats that are checked in exclusive mode. The default is to check 32-bit floating-point, 32-bit integer, 24-bit integer, 16-bit integer, 8-bit integer, in that order. A BASS_WASAPI_FORMAT value (see BASS_WASAPI_INFO) can be used to bypass the formats that precede it in that list. + + + If the sample format is supported, the maximum supported resolution (a value) is returned, else -1 is returned. Use to get the error code. + + Call this method prior to in order to make sure the requested format is supported by the Wasapi output device/driver (endpoint). + Shared and exclusive modes may have different sample formats available. + Only the "mix format" (available from ) is generally supported in shared mode. + + + ERROR CODEDescription + BASS_ERROR_WASAPIWASAPI is not available. + BASS_ERROR_DEVICEThe number specified is invalid. + BASS_ERROR_DRIVERThe driver could not be initialized. + BASS_ERROR_FORMATUnsupported sample format or number of channels. + + + + + + + Checks if a particular sample format is supported by a device (endpoint) in exclusive mode. + + The device to use... 0 = first device, -1 = default device, -2 = default input device. can be used to enumerate the available devices. + The sample rate to check. + The number of channels to check... 1 = mono, 2 = stereo, etc. + Limit the sample format that is used in exclusive mode. The default is to try 32-bit floating-point, 32-bit integer, 24-bit integer, 16-bit integer, 8-bit integer, in that order. A BASS_WASAPI_FORMAT value (see ) can be used to bypass the formats that precede it in that list. + If the sample format is supported, the maximum supported resolution (a value) is returned, else -1 is returned. Use to get the error code. + + This overload always uses the BASS_WASAPI_EXCLUSIVE flag which will be applied automatically! + The parameter can be used to limit the sample format that is used in exclusive mode. + Call this method prior to in order to make sure the requested format is supported by the Wasapi output device/driver (endpoint). + Shared and exclusive modes may have different sample formats available. + Only the "mix format" (available from ) is generally supported in shared mode. + + + ERROR CODEDescription + BASS_ERROR_WASAPIWASAPI is not available. + BASS_ERROR_DEVICEThe number specified is invalid. + BASS_ERROR_DRIVERThe driver could not be initialized. + BASS_ERROR_FORMATUnsupported sample format or number of channels. + + + + + + + Initializes a Wasapi device/driver (endpoint). + + The device to use... 0 = first device, -1 = default output device, -2 = default input device. can be used to enumerate the available devices. + The sample rate to use... 0 = "mix format" sample rate. + The number of channels to use... 0 = "mix format" channels, 1 = mono, 2 = stereo, etc. + Any combination of these flags (see ): + + BASS_WASAPI_SHAREDOpen the device in shared mode. + BASS_WASAPI_EXCLUSIVEInitialize the device in exclusive mode, else shared mode. + The HIWORD - use Utils.MakeLong(flags,format) - can be used to limit the sample format that is used in exclusive mode. The default is to try 32-bit floating-point, 32-bit integer, 24-bit integer, 16-bit integer, 8-bit integer, in that order. A BASS_WASAPI_FORMAT value (see ) can be used to bypass the formats that precede it in that list. + BASS_WASAPI_AUTOFORMATAutomatically choose another sample format if the specified format is not supported. If possible, a higher sample rate than freq will be used, rather than a lower one. + BASS_WASAPI_BUFFEREnable double buffering, for use by and . This requires the BASS "no sound" device to have been initilized, via . + BASS_WASAPI_SESSIONVOLDeal with the session volume rather than the device volume. When used with shared mode output, session volume limits the effect of and to the current process; other users of the device are unaffected. + Session volume has no effect on exclusive mode output, and maps to the device volume with input devices (so does affect other users). + + + The length of the device's buffer in seconds. This is a minimum and the driver may choose to use a larger buffer; can be used to confirm what the buffer size is. For an output device, the buffer size determines the latency. + The interval (in seconds) between callback function calls... 0 = use default. If the specified period is below the minimum update period, it will automatically be raised to that. + The update period specifies the time between calls. + The (see ) "minperiod" and "defperiod" values are actually minimum/default update periods. + + + The user defined function to process the channel. Use to create a Wasapi "push" device (to which you can feed sample data via ). + User instance data to pass to the callback function. + If the device was successfully initialized, is returned, else is returned. Use to get the error code. + + For convenience, devices are always initialized to use their highest sample resolution and that is then converted to 32-bit floating-point, so that WASAPIPROC callback functions and the and functions are always dealing with the same sample format. + The device's sample format can be obtained via . + WASAPI does not support arbitrary sample formats, like DirectSound does. In particular, only the "mix format" (available from ) is generally supported in shared mode. + can be used to check whether a particular sample format is supported. The BASSmix add-on can be used to play (or record) in otherwise unsupported sample formats, as well as playing multiple sources. + The initialized device will not begin processing data until is called. + Simultaneously using multiple devices is supported in the BASS API via a context switching system; instead of there being an extra "device" parameter in the function calls, the device to be used is set prior to calling the functions. is used to switch the current device. + When successful, automatically sets the current thread's device to the one that was just initialized. + When using the default output or input device, can be used to find out which device it was mapped to. + In SHARED mode you must initialize the device with the current WASAPI mixer sample rate and number of channels (see the "mixfreq" and "mixchans" properties). + In EXCLUSIVE mode you might use any sample rate and number of channels which are supported by the device/driver. + This function must be successfully called before any input or output can be performed. + In EXCLUSIVE mode, the "period" value will affect what's an acceptable "buffer" value (it appears that the buffer must be at least 4x the period). + In SHARED mode, it's the other way round, the "period" will be reduced to fit the "buffer" if necessary (with a minimum of the "defperiod" value). + The system will limit them to an acceptable range, so for example, you could use a very small value (eg. 0.0001) for both, to get the minimum possible latency. + Note: When initializing an input (capture or loopback) device, it might be the case, that the device is automatically muted once initialized. + You can use the / methods to check and probably toggle this. + + + ERROR CODEDescription + BASS_ERROR_WASAPIWASAPI is not available. + BASS_ERROR_DEVICEThe number specified is invalid. + BASS_ERROR_ALREADYA device has already been initialized. You must call before you can initialize again. + BASS_ERROR_ILLPARAMAn illegal parameter was specified (a WASAPIPROC must be provided for an input device). + BASS_ERROR_DRIVERThe driver could not be initialized. + BASS_ERROR_FORMATThe specified format is not supported by the device. If the BASS_WASAPI_AUTOFORMAT flag was specified, no other format could be found either. + BASS_ERROR_INITThe BASS "no sound" device has not been initialized. + BASS_ERROR_BUSYThe device is busy (eg. in "exclusive" use by another process). + BASS_ERROR_UNKNOWNSome other mystery error. + + + + + + + Initializes a Wasapi device/driver (endpoint) in exclusive mode. + + The device to use... 0 = first device, -1 = default output device, -2 = default input device. can be used to enumerate the available devices. + The sample rate to use... 0 = "mix format" sample rate. + The number of channels to use... 0 = "mix format" channels, 1 = mono, 2 = stereo, etc. + Any combination of these flags (see ): + + BASS_WASAPI_EXCLUSIVEThis flag will be applied automatically by this overload! + The parameter can be used to limit the sample format that is used in exclusive mode. + BASS_WASAPI_AUTOFORMATAutomatically choose another sample format if the specified format is not supported. If possible, a higher sample rate than freq will be used, rather than a lower one. + BASS_WASAPI_BUFFEREnable double buffering, for use by and . This requires the BASS "no sound" device to have been initilized, via . + BASS_WASAPI_SESSIONVOLDeal with the session volume rather than the device volume. When used with shared mode output, session volume limits the effect of and to the current process; other users of the device are unaffected. + Session volume has no effect on exclusive mode output, and maps to the device volume with input devices (so does affect other users). + + + Limit the sample format that is used in exclusive mode. The default is to try 32-bit floating-point, 32-bit integer, 24-bit integer, 16-bit integer, 8-bit integer, in that order. A BASS_WASAPI_FORMAT value (see ) can be used to bypass the formats that precede it in that list. + The length of the device's buffer in seconds. This is a minimum and the driver may choose to use a larger buffer; can be used to confirm what the buffer size is. For an output device, the buffer size determines the latency. + The interval (in seconds) between callback function calls... 0 = use default. If the specified period is below the minimum update period, it will automatically be raised to that. + The update period specifies the time between calls. + The (see ) "minperiod" and "defperiod" values are actually minimum/default update periods. + + + The user defined function to process the channel. Use to create a Wasapi "push" device (to which you can feed sample data via ). + User instance data to pass to the callback function. + If the device was successfully initialized, is returned, else is returned. Use to get the error code. + + For convenience, devices are always initialized to use their highest sample resolution and that is then converted to 32-bit floating-point, so that WASAPIPROC callback functions and the and functions are always dealing with the same sample format. + The device's sample format can be obtained via . + WASAPI does not support arbitrary sample formats, like DirectSound does. In particular, only the "mix format" (available from ) is generally supported in shared mode. + can be used to check whether a particular sample format is supported. The BASSmix add-on can be used to play (or record) in otherwise unsupported sample formats, as well as playing multiple sources. + The initialized device will not begin processing data until is called. + Simultaneously using multiple devices is supported in the BASS API via a context switching system; instead of there being an extra "device" parameter in the function calls, the device to be used is set prior to calling the functions. is used to switch the current device. + When successful, automatically sets the current thread's device to the one that was just initialized. + When using the default output or input device, can be used to find out which device it was mapped to. + In SHARED mode you must initialize the device with the current WASAPI mixer sample rate and number of channels (see the "mixfreq" and "mixchans" properties). + In EXCLUSIVE mode you might use any sample rate and number of channels which are supported by the device/driver. + This function must be successfully called before any input or output can be performed. + In EXCLUSIVE mode, the "period" value will affect what's an acceptable "buffer" value (it appears that the buffer must be at least 4x the period). + In SHARED mode, it's the other way round, the "period" will be reduced to fit the "buffer" if necessary (with a minimum of the "defperiod" value). + The system will limit them to an acceptable range, so for example, you could use a very small value (eg. 0.0001) for both, to get the minimum possible latency. + Note: When initializing an input (capture or loopback) device, it might be the case, that the device is automatically muted once initialized. + You can use the / methods to check and probably toggle this. + + + ERROR CODEDescription + BASS_ERROR_WASAPIWASAPI is not available. + BASS_ERROR_DEVICEThe number specified is invalid. + BASS_ERROR_ALREADYA device has already been initialized. You must call before you can initialize again. + BASS_ERROR_ILLPARAMAn illegal parameter was specified (a WASAPIPROC must be provided for an input device). + BASS_ERROR_DRIVERThe driver could not be initialized. + BASS_ERROR_FORMATThe specified format is not supported by the device. If the BASS_WASAPI_AUTOFORMAT flag was specified, no other format could be found either. + BASS_ERROR_INITThe BASS "no sound" device has not been initialized. + BASS_ERROR_BUSYThe device is busy (eg. in "exclusive" use by another process). + BASS_ERROR_UNKNOWNSome other mystery error. + + + + + + + Frees the Wasapi device/driver (endpoint). + + If successful, then is returned, else is returned. Use to get the error code. + This function should be called for all initialized devices before the program closes. Freed devices do not need to have been stopped with beforehand. + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + + + + + + + Retrieves information on the Wasapi device being used. + + An instance of the class to store the information at. + If successful, then is returned, else is returned. Use to get the error code. + This method can be used to get the effective settings used with an initialized WASAPI device (endpoint). + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + + + + + + + Retrieves information on the Wasapi device being used. + + An instance of the class on success - else . + This method can be used to get the effective settings used with an initialized WASAPI device (endpoint). + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + + + + + + + Starts processing the current Wasapi device/driver (endpoint). + + If successful, then is returned, else is returned. Use to get the error code. + Before starting the device, it must be initialized using . Use to stop processing the device. + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Stops the current Wasapi device/driver (endpoint). + + Flush the device buffer? + will clear the output buffer. Otherwise it is like pausing, eg. will resume playing the buffered data. + + If successful, then is returned, else is returned. Use to get the error code. + + If the device buffer is left unflushed (reset=FALSE), a subsequent call will resume things with the buffered data, otherwise it will resume with fresh data. + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_STARTThe device hasn't been started. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Checks, if the current Wasapi device/driver (endpoint) has been already started (via ). + + Returns , if the device has been started, else is returned. Use to get the error code. + + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + + + Retrieves the current CPU usage of BASSWASAPI. + + The BASSWASAPI CPU usage as a percentage of total CPU time. + This function includes the time taken by the callback functions. + + + + Locks the device to the current thread. + + If , unlock WASAPI, else lock it. + If successful, is returned, else is returned. Use to get the error code. + + Locking a device prevents other threads from accessing the device buffer, including a WASAPIPROC. Other threads wanting to access a locked device will block until it is unlocked, so a device should only be locked very briefly. + A device must be unlocked in the same thread that it was locked. + + + + + Sets the volume of the current Wasapi device/driver (endpoint). + + to set the volume linear (0.0=MindB...1.0=MaxdB) - else set the logarithmic in dB (see the volmax and volmin members for a valid range). + The new volume to set between 0.0 (silent) and 1.0 (maximum) if linear, or else a dB level. + Returns on success, else is returned. Use to get the error code. + This method sets the global device or session volume (depending what flags you used with your call) and not the volume of the individual stream being processed. + If you need to control the volume of the stream only you need to apply that directly within the yourself. + When setting the volume in dB (linear = ), the valid range can be obtained from . + When dealing with the session volume, the valid range is 0 dB and below. + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILThere is no volume control available. + BASS_ERROR_ILLPARAM is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Retrieves the current volume level. + + to get the volume linear (0.0=MindB...1.0=MaxdB) - else get the volume logarithmic in dB. + If was set to , the linear volume between 0.0 (silent, MindB) and 1.0 (maximum, MaxdB) is returned - else the volume in dB is returned. + This method returns either the global device or the session volume (depending what flags you used with your call). + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILThere is no volume control available. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Adds sample data to an output device buffer ("push" device). + + The pointer to the sample data to provide. + The amount of data in bytes! (buffer.Length/4). with the BASS_DATA_AVAILABLE flag can be used to check how much data is queued. + If successful, the the amount of data copied from the provided buffer will be returned (which may be less than requested if it doesn't all fit in the device buffer, see the "buflen" property), else -1 is returned. Use to get the error code. + You must have initialized the device via using for the . + As much data as possible will be placed in the device's buffer; this function will have to be called again for any remainder. + Data should be provided at a rate sufficent to sustain playback. If the buffer gets exhausted, ouput will stall until more data is provided. (BASS_DATA_AVAILABLE) can be used to check how much data is buffered. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILThe device is being fed by a WASAPIPROC callback function, or it is an input device. + BASS_ERROR_ILLPARAM is not valid, it must equate to a whole number of samples. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Adds sample data to an output device buffer ("push" device). + + The array of float sample data to provide. + The amount of data in bytes! (buffer.Length/4). with the BASS_DATA_AVAILABLE flag can be used to check how much data is queued. + If successful, the the amount of data copied from the provided buffer will be returned (which may be less than requested if it doesn't all fit in the device buffer, see the "buflen" property), else -1 is returned. Use to get the error code. + You must have initialized the device via using for the . + As much data as possible will be placed in the device's buffer; this function will have to be called again for any remainder. + Data should be provided at a rate sufficent to sustain playback. If the buffer gets exhausted, ouput will stall until more data is provided. (BASS_DATA_AVAILABLE) can be used to check how much data is buffered. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILThe device is being fed by a WASAPIPROC callback function, or it is an input device. + BASS_ERROR_ILLPARAM is not valid, it must equate to a whole number of samples. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Retrieves the level (peak amplitude) of the current Wasapi device/driver (endpoint). + + If an error occurs, -1 is returned, use to get the error code. + If successful, the level of the left channel is returned in the low word (low 16-bits, use ), and the level of the right channel is returned in the high word (high 16-bits, use ). If the channel is mono, then the low word is duplicated in the high word. + The level ranges linearly from 0 (silent) to 32768 (max). 0 will be returned when a channel is stalled. + + + This function is like the standard , but it gets the level from the devices's buffer instead of decoding data from a channel, which means that the device doesn't miss out on any data. + The BASS_WASAPI_BUFFER flag needs to have been specified in the device's initialization to enable the use of this function. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILThe device was not initialized using buffering (BASS_WASAPI_BUFFER). + + + + + + + Retrieves the immediate sample data (or an FFT representation of it) of the current Wasapi device/driver (endpoint). + This overload uses an IntPtr to reference the buffer data. + + Location to write the data to. + Use "Marshal.AllocCoTaskMem" to allocate a memory buffer, use "Marshal.Copy" to copy the buffer data from unmanaged BASS to your managed code and use "Marshal.FreeCoTaskMem" to free the memory buffer when not needed anymore. + Or make use of a "GCHandle" to receive data to a pinned managed object. + + Number of bytes wanted, and/or the following flags (): + + BASS_DATA_FLOATReturn floating-point sample data. + BASS_DATA_FFT256256 sample FFT (returns 128 floating-point values) + BASS_DATA_FFT512512 sample FFT (returns 256 floating-point values) + BASS_DATA_FFT10241024 sample FFT (returns 512 floating-point values) + BASS_DATA_FFT20482048 sample FFT (returns 1024 floating-point values) + BASS_DATA_FFT40964096 sample FFT (returns 2048 floating-point values) + BASS_DATA_FFT81928192 sample FFT (returns 4096 floating-point values) + BASS_DATA_FFT_INDIVIDUALUse this flag to request separate FFT data for each channel. The size of the data returned (as listed above) is multiplied by the number channels. + BASS_DATA_FFT_NOWINDOWThis flag can be used to prevent a hanning window being applied to the sample data when performing an FFT. + BASS_DATA_AVAILABLEQuery the amount of data the device has buffered (the BASS_WASAPI_BUFFER flag isn't required for this, can be when using this flag). + + + If an error occurs, -1 is returned, use to get the error code. + When requesting FFT data, the number of bytes read from the device (to perform the FFT) is returned. + When requesting sample data, the number of bytes written to buffer will be returned (not necessarily the same as the number of bytes read when using the BASS_DATA_FLOAT flag). + When using the BASS_DATA_AVAILABLE flag, the number of bytes in the device's buffer is returned. + + + This function is like the standard , but it gets the data from the device's buffer instead of decoding it from a channel, + which means that the device doesn't miss out on any data. In order to do this, the device must have buffering enabled, via the BASS_MIXER_BUFFER flag. + Internally, a BASS stream is used for that, so the usual BASS_DATA_xxx flags are supported. That also means that BASS needs to have been initialized first; it specifically uses the "no sound" device. + If the device is subsequently freed, this method call will fail. + As in BASS, simultaneously using multiple devices is supported in the BASSWASAPI API via a context switching system - instead of there being an extra "device" parameter in the function calls, + the device to be used needs to be set via prior to calling the function. + The device setting is local to the current thread, so calling functions with different devices simultaneously in multiple threads is not a problem. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILThe device was not initialized using buffering (BASS_WASAPI_BUFFER). + + + + + + + Retrieves the immediate sample data (or an FFT representation of it) of the current Wasapi device/driver (endpoint). + This overload uses a managed float[] to reference the buffer data as 32-bit! + + The array (float[]) to write the data to. + Number of bytes wanted, and/or the following flags (): + + BASS_DATA_FLOATReturn floating-point sample data. + BASS_DATA_FFT256256 sample FFT (returns 128 floating-point values) + BASS_DATA_FFT512512 sample FFT (returns 256 floating-point values) + BASS_DATA_FFT10241024 sample FFT (returns 512 floating-point values) + BASS_DATA_FFT20482048 sample FFT (returns 1024 floating-point values) + BASS_DATA_FFT40964096 sample FFT (returns 2048 floating-point values) + BASS_DATA_FFT81928192 sample FFT (returns 4096 floating-point values) + BASS_DATA_FFT_INDIVIDUALUse this flag to request separate FFT data for each channel. The size of the data returned (as listed above) is multiplied by the number channels. + BASS_DATA_FFT_NOWINDOWThis flag can be used to prevent a hanning window being applied to the sample data when performing an FFT. + BASS_DATA_AVAILABLEQuery the amount of data the device has buffered (the BASS_WASAPI_BUFFER flag isn't required for this, can be when using this flag). + + + If an error occurs, -1 is returned, use to get the error code. + When requesting FFT data, the number of bytes read from the device (to perform the FFT) is returned. + When requesting sample data, the number of bytes written to buffer will be returned (not necessarily the same as the number of bytes read when using the BASS_DATA_FLOAT flag). + When using the BASS_DATA_AVAILABLE flag, the number of bytes in the device's buffer is returned. + + + This function is like the standard , but it gets the data from the device's buffer instead of decoding it from a channel, + which means that the device doesn't miss out on any data. In order to do this, the device must have buffering enabled, via the BASS_MIXER_BUFFER flag. + As in BASS, simultaneously using multiple devices is supported in the BASSWASAPI API via a context switching system - instead of there being an extra "device" parameter in the function calls, + the device to be used needs to be set via prior to calling the function. + The device setting is local to the current thread, so calling functions with different devices simultaneously in multiple threads is not a problem. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILThe device was not initialized using buffering (BASS_WASAPI_BUFFER). + + + + + + + Gets the audio meter information of the current Wasapi device/driver (endpoint). + + The device to use... 0 = first device. can be used to get the total number of devices. + The channel number to get the audio level meter information from (0=first, -1=all). + The audio level between 0.0 (silence) and 1.0 (maximum). + This method returns the global session level for the device which might include the level of other applications using the same device in shared-mode. + This function gets the level from the device/driver, or WASAPI if the device does not have its own level meter. If the latter case, the level will be unavailable when exclusive mode is active. + + + ERROR CODEDescription + BASS_ERROR_WASAPIWASAPI is not available. + BASS_ERROR_DEVICE is not valid. + BASS_ERROR_DRIVERThe device driver does not support level retrieval. + BASS_ERROR_ILLPARAM is not valid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Sets the mute status of the current Wasapi device/driver (endpoint). + + to mute the device, to unmute the device. + If successful, then is returned, else is returned. Use to get the error code. + This method sets the global session mute state, meaning using this method might effect other applications too. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILThere is no volume control available. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Gets the mute status of the current Wasapi device/driver (endpoint). + + Returns , if the device is muted and if unmuted, else -1 is returned. Use to get the error code. + This method returns the global session mute state. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILThere is no volume control available. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Sets a device change notification callback. + + User defined notification function... = disable notifications. + User instance data to pass to the callback function. + If successful, is returned, else is returned. Use to get the error code. + + A previously set notification callback can be changed (or removed) at any time, by calling this function again. + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + Load BASS and BASSWMA from the application's startup path: + + Bass.LoadMe(); + BassWma.LoadMe(); + ... + // when not used anymore... + BassWma.FreeMe(); + Bass.FreeMe(); + + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + Load BASS and BASSWMA from a different directory: + + Bass.LoadMe( @"C:\Development\BASS\_libs" ); + BassWma.LoadMe( @"C:\Development\BASS\_libs" ); + ... + // when not used anymore... + BassWma.FreeMe(); + Bass.FreeMe(); + + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + BassWasapi device info types to be used with and . + + + + + A network device. + + + + + A speakers device. + + + + + A line level device. + + + + + A headphone device. + + + + + A microphone device. + + + + + A headset device. + + + + + A handset device. + + + + + A digital device. + + + + + A S/PDIF device. + + + + + A HDMI device. + + + + + An unknown device. + + + + + BassWasapi device info flags to be used with and . + + + + + Unknown flags. + E.g. the WASAPI device is not present. + + + + + The WASAPI device is enabled (active). + + + + + The WASAPI device is the default device. + + + + + The WASAPI device is initialized. + + + + + The WASAPI device is a loopback device. + + + + + The WASAPI device is an input (capture) device. + + + + + The WASAPI device is unplugged. + + + + + The WASAPI device is disabled. + + + + + BassWasapi initialization flags to be used with . + + + + + Init the device (endpoint) in shared mode. + + + + + Init the device (endpoint) in exclusive mode. + + + + + Automatically choose another sample format if the specified format is not supported. + If possible, a higher sample rate than freq will be used, rather than a lower one. + + + + + Enable double buffering, for use by and . + This requires the BASS "no sound" device to have been initilized, via . + Internally, a BASS stream is used for that, so the usual BASS_DATA_xxx flags are supported. + + + + + Deal with the session volume rather than the device volume. + When used with shared mode output, session volume limits the effect of and to the current process; + other users of the device are unaffected. Session volume has no effect on exclusive mode output, and maps to the device volume with input devices (so does affect other users). + + + + + BassWasapi sample formats to be used with and . + + + + + 32-bit floating-point. + + + + + 32-bit floating-point. + + + + + 8-bit integer. + + + + + 16-bit integer. + + + + + 24-bit integer. + + + + + 32-bit integer. + + + + + BassWasapi sample formats to be used with and . + + + + + The device's status has changed, eg. it has been enabled or disabled. The new status is available from . + + + + + The device is now the default input device. + + + + + The device is now the default output device. + + + + + Used with to retrieve information on a Wasapi device. + + + + + The description of the device. + + + + + The ID of the driver being used. + + The "id" can be matched-up the "driver", to match-up the WASAPI and DirectSound device list entries. + + + + The type of the devices. One of the values. + + + + + The device's current and input/output status. Any combination of . + + + + + The minimum update period (in seconds) of the device. + + + + + The default update period (in seconds) of the device. + + + + + The shared-mode format mixers sample rate. + + + + + The shared-mode format mixers number of channels. + + + + + Default constructor. + + + + + A description of the decive info object (name). + + The name of the device/driver. + + + + The device is enabled and can be used (i.e. it is active). + + + + + The device is plugged but disabled (in the windows sound control panel) and can not be used. + + + + + The device is unplugged and can not be used. + + + + + The device is the system default device. + + + + + The device is already initialized. + + + + + The device is a loopback device (capturing from output). + + + + + The device is an input (capture) device. + + + + + The device supportes recording (either an INPUT or LOOPBACK device). + + + + + Used with to retrieve information on the current device. + + + + + The flags parameter of the call. + + + + + The sample rate used. + + + + + The number of channels used (1 = mono, 2 = stereo, etc.). + + + + + The device's sample format used (one of the ). + + + + + The buffer size in bytes. + + + + + The maximum volume setting in dB. + + + + + The minimum volume setting in dB. + + + + + The volume step size in dB. + + + + + Default constructor. + + + + + A description of the decive info object (the format, sample rate and number of channels). + + The description string of the device/driver. + + + + Is the device used in exclusive mode? + + + + + Is the device being initialized using session volume (instead of global device volume)? + + + + + User defined WASAPI output/input processing callback function (to be used with ). + + Pointer to the buffer to put the sample data for an output device, or to get the data from an input device. The sample data is always 32-bit floating-point. + The number of bytes to process. + The user instance data given when was called. + In the case of an output device, the number of bytes written to the buffer. In the case of an input device, 0 = stop the device, else continue. + + An output/input processing function should obviously be as quick as possible, to avoid buffer underruns (output) or overruns (input). Using a larger buffer makes that less crucial. (BASS_DATA_AVAILABLE) can be used to check how much data is buffered. + An output device's WASAPIPROC may return less data than requested, but be careful not to do so by too much, too often. If the buffer gets exhausted, output will stall until more data is provided. If you do return less than the requested amount of data, the number of bytes should still equate to a whole number of samples. + When multiple channels are used, the sample data of the channels is interleaved. For example, with 2 channels (ie. stereo), the sample data would be arranged as channel 1, channel 2, channel 1, channel 2, channel 1, etc. + When an output channel needs to be empty/silent but still enabled, the channel's function could fill the buffer with 0s to achieve that. + Do not call from within a callback function. + Prior to calling this function, BASSWASAPI will set the thread's device context to the device that the channel belongs to. So when using multiple devices, can be used to determine which device the channel is on. + NOTE: When you pass an instance of a callback delegate to one of the BASS functions, this delegate object will not be reference counted. + This means .NET would not know, that it might still being used by BASS. The Garbage Collector might (re)move the delegate instance, if the variable holding the delegate is not declared as global. + So make sure to always keep your delegate instance in a variable which lives as long as BASS needs it, e.g. use a global variable or member. + It is not supported to change the once a device was initialized via . + If you need to change some internal processing logic during processing, you might use some kind of "if" statements within this callback procedure. + + + + + User defined notification callback function. + + The notification, one of the following: + + BASS_WASAPI_NOTIFY_CHANGEThe device's status has changed, eg. it has been enabled or disabled. The new status is available from . + BASS_WASAPI_NOTIFY_DEFINPUTThe device is now the default input device. + BASS_WASAPI_NOTIFY_DEFOUTPUTThe device is now the default output device. + + + The device that the notification applies to. + The user instance data given when was called. + + + + This class provides ready-made members for direct and more simple WASAPI usage together with BASS channels. + + + You might use this class for almost all use cases in terms of Wasapi handling, e.g.: + + Scenario:How-To: + Wasapi outputA Bass decoding channel feeding Wasapi output. + Simply create an instance of this class using an output device endpoint and then call the method to add your decoding channel(s) to be used for output. + Now you call the and methods to actually start the Wasapi output processing. + You might also use the property (which returns the internally used mixer channel) to add or remove any decoding channel yourself. + + Wasapi inputDirectly record from Wasapi input. + Simply create an instance of this class using an input device endpoint you want to record at (this automatically sets the property to ). + To retrieve the input sample data use the channel (e.g. setup an own DSP, use it with the or Encoder Framework). + + Wasapi input, full-duplex to WasapiMonitor your Wasapi input on any Wasapi output. + Not supported directly by this class (but you can simply do this yourself, by initializing an output device with a and calling from within your input devices ). + + Wasapi input, full-duplex to BASSMonitor your Wasapi input on any BASS device. + To enable full-duplex just call the method (when done call ). + Note: You might also specify the "no sound" BASS device (0) and use the with the call in order to retrieve a full-duplex decoding Bass stream, which you can now assign to an output instance of this class via to preform a full-duplex Wasapi input to output monitoring. + + DSP/FXYou can set any DSP/FX on either the input and/or the output (full-duplex). + See and for more details. + + In addition to the above this class supports overloading of the default Wasapi callbacks (, ). + + You might use the and properties to easily control your Wasapi input/output settings. + Wasapi channels can be paused and resumed at any time by using the method. + To physically start the Wasapi device the followed by methods might be used. will disable and stop the Wasapi device (if really needed). + Caution: Once you created an instance of this class and called the method, the respective WASAPI device is enabled and a session is created. + The used WASAPI device will be disabled and freed automatically when an instance of this class is being disposed by the .Net Garbage Collector! + Call the method manually to free the WASAPI device, including any full-duplex options. + Note: This class internally uses as well as the add-on, so you need to provide the native bass.dll and the bassmix.dll as well when using this class. + + + Automatic use of the BassWasapiHandler (a Bass channel is feeding Wasapi output): + + private BassWasapiHandler _wasapi; + ... + // not playing anything via BASS, so don't need an update thread + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0); + // setup BASS - "no sound" device + Bass.BASS_Init(0, 48000, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero); + ... + int stream = Bass.BASS_StreamCreateFile(fileName, 0, 0, + BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); + if (stream != 0) + { + // assign WASAPI output in shared-mode + _wasapi = new BassWasapiHandler(-1, false, 48000, 2, 0f, 0f); + // add the source channel + _wasapi.AddOutputSource(stream, BASSFlag.BASS_DEFAULT) + // init and start WASAPI + _wasapi.Init(); + _wasapi.Start(); + } + + + Private _wasapi As BassWasapiHandler + ... + ' not playing anything via BASS, so don't need an update thread + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0) + ' setup BASS - "no sound" device + Bass.BASS_Init(0, 48000, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile(fileName, 0, 0, + BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT) + If stream <> 0 Then + ' assign WASAPI output in shared-mode + _wasapi = new BassWasapiHandler(-1, false, 48000, 2, 0f, 0f) + ' add the source channel + _wasapi.AddOutputSource(stream, BASSFlag.BASS_DEFAULT) + ' init and start WASAPI + _wasapi.Init() + _wasapi.Start() + End If + + Automatic use of the BassWasapiHandler (Wasapi recording input): + + private BassWasapiHandler _wasapi; + ... + // not playing anything via BASS, so don't need an update thread + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0); + // setup BASS - "no sound" device + Bass.BASS_Init(0, 48000, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero); + ... + // assign WASAPI input in shared-mode + _wasapi = new BassWasapiHandler(-2, false, 48000, 2, 0f, 0f); + // init and start WASAPI + _wasapi.Init(); + int recordStream = _wasapi.InputChannel; + // double check, that the device is not muted externally + if (_wasapi.DeviceMute) + _wasapi.DeviceMute = false; + _wasapi.Start(); + ... + // now you can use recordStream to setup any DSP/FX etc. + + + Private _wasapi As BassWasapiHandler + ... + ' not playing anything via BASS, so don't need an update thread + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0) + ' setup BASS - "no sound" device + Bass.BASS_Init(0, 48000, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) + ... + ' assign WASAPI input in shared-mode + _wasapi = new BassWasapiHandler(-2, false, 48000, 2, 0f, 0f) + ' init and start WASAPI + _wasapi.Init() + Dim recordStream As Integer = _wasapi.InputChannel + ' double check, that the device is not muted externally + If _wasapi.DeviceMute Then + _wasapi.DeviceMute = False + End If + _wasapi.Start() + End If + ... + ' now you can use recordStream to setup any DSP/FX etc. + + Setup a full-duplex stream on Wasapi input and pass that to an Wasapi output instance: + + // setup a full-duplex stream + _wasapiInput.SetFullDuplex(0, BASSFlag.BASS_STREAM_DECODE, false, 2000); + int fullDuplexStream = _wasapiInput.OutputChannel; + // and assign it to an output + _wasapiOutput.AddOutputSource(fullDuplexStream, BASSFlag.BASS_DEFAULT); + + + ' setup a full-duplex stream + _wasapiInput.SetFullDuplex(0, BASSFlag.BASS_STREAM_DECODE, False, 2000) + Dim fullDuplexStream As Integer = _wasapiInput.OutputChannel + ' and assign it to an output + _wasapiOutput.AddOutputSource(fullDuplexStream, BASSFlag.BASS_DEFAULT) + + + + + + Creates an instance of the WASAPI handler. + + The device to use... 0 = first device. + Use the WASAPI device in exclusive mode? + The sample rate to use (only used in exclusive mode, in shared mode the default mixer sample rate is used). + The number of channels to use (only used in exclusive mode, in shared mode the default mixer number of channels are used). + The buffer size (in seconds) to use (set to 0 to use the default buffer length). + The update period (in seconds) to use (set to 0 to use the default update period). + + The instance automatically detects according to the being used, if this handler will be dealing with as input (capture or loopback) or with output (rendering) endpoint device. + You might use the property to validate this. + Exclusive Mode: The requested number of channels are used. The requested sample rate is used. + Shared Mode: The default mixer number of channels are used. The default mixer sample rate is used (the parameter is ignored). + + Invalid device: the Wasapi device is invalid. + Internal Mixer: the internal mixer cannot be created (e.g. was never called). + + + + Creates an instance of the WASAPI handler. + + The device to use... 0 = first device. + Use the WASAPI device in exclusive mode? + Use session volume control? + The sample rate to use (only used in exclusive mode, in shared mode the default mixer sample rate is used). + The number of channels to use (only used in exclusive mode, in shared mode the default mixer number of channels are used). + The buffer size (in seconds) to use (set to 0 to use the default buffer length). + The update period (in seconds) to use (set to 0 to use the default update period). + + The instance automatically detects according to the being used, if this handler will be dealing with as input (capture or loopback) or with output (rendering) endpoint device. + You might use the property to validate this. + Exclusive Mode: The requested number of channels are used. The requested sample rate is used. + Shared Mode: The default mixer number of channels are used. The default mixer sample rate is used (the parameter is ignored). + Session volume limits the effect of and to the current process; other users of the device are unaffected. + Session volume has no effect on exclusive mode output, and maps to the device volume with input devices (so does affect other users). + + Invalid device: the Wasapi device is invalid. + Internal Mixer: the internal mixer cannot be created (e.g. was never called). + + + + Disposes an instance of this class also stops and frees the used WASAPI device/driver (endpoint). + + The used WASAPI device/driver (endpoint) will be stopped and freed! + Caution: Once you created an instance of this class and called , the respective WASAPI device/driver (endpoint) is initialized. + Calling this method will automatically stopp and free the used WASAPI device/driver (endpoint) as well as the full-duplex option will be removed! + + + + + Finalization code. + + This destructor will run only if the Dispose method does not get called. + It gives your base class the opportunity to finalize. Do not provide destructors in types derived from this class. + + + + Initialises the WASAPI (must be called before ). + + If successful, then is returned, else is returned. Use to get the error code. + + + + Starts the WASAPI . + + If successful, then is returned, else is returned. Use to get the error code. + Calls internally on the being used by the Wasapi handler (if not already started). + If you need to stop the WASAPI device you might call . + + + + + Stops the WASAPI . + + If successful, then is returned, else is returned. Use to get the error code. + Calls internally on the being used by the Wasapi handler (if not already stopped). + If you need to start the WASAPI device you might call . + + + + + Pauses or Unpauses the WASAPI being used. + + if you want to pause the WASAPI device - if you want to unpause. + On success is returned, else will be returned (use to retrieve the error code). + + + + Adds a new source to the WASAPI handler for output. + + The decoding stream to add to the output (must be a decoding channel). + The speaker flags to use with the channel (use BASS_DEFAULT or any of the BASS_SPEAKER_xxx flags). + On success is returned, else will be returned (use to retrieve the error code). + + In case the Wasapi handler is used for output an is always internally created in order to handle possible resampling. + You might use this method to add new source channels to this internal mixer in order to play them to the output. + Note, that the following flags will be added automatically as necessary: BASS_MIXER_DOWNMIX (in case you don't provide any speaker flags), BASS_MIXER_FILTER (in case the 's sample rate doesn't match the ). + + + + + Sets the full-duplex option for WASAPI input using the given BASS output device. + + The BASS output device which should be used for full-duplex monitoring. + The optional flags to be used to create the full-duplex monitoring . + Typically only the following flags should be used: BASS_STREAM_DECODE, BASS_SAMPLE_SOFTWARE or BASS_SPEAKER_xxx. + , if the should be (pre)buffered - else . + Prebuffering of sample data is often requied for buffered output to enable a constant playback. So even if you are using a BASS_STREAM_DECODE flag you might need to prebuffer it's data. + + On success is returned, else will be returned (use to retrieve the error code). + + The following will be done internally: + 1. The BASS output will be used. + 2. A custom push stream (see ) will be created (using the given ) with an internal WASAPI callback feeding the stream with the sample data from the input. + 3. The samplerate, format and number of channels will not be changed for WASAPI input, since this will be used as already specified in the constructor. + 4. The custom push stream will be started playing (via ) - unless the flag has been specified. + This method can not be used with WASAPI output (see ). It will immediately return with no effect. + To disable and remove the full-duplex option call . + The full-duplex BASS output is provided by the internal custom push stream . You might use this stream to set up DSPs or FX on it so that these are applied on the BASS output. + You might use the 0 (no-sound) bass device together with the BASS_STREAM_DECODE flag in order to create a custom decoding which might for example be used with an or or + as a source for a mixer channel. + + + + + Removes the full-duplex option from WASAPI input. + + On success is returned, else will be returned (use to retrieve the error code). + The full-duplex option must have been set before via . + This method can not be used with WASAPI output (see ). It will immediately return with no effect. + To enable the full-duplex option again, call . + + + + + Provides a ready made callback procedure which might be used for WASAPI output. + + The pointer to the buffer in which to put the data to output. Will always be floating point! + The number of bytes to process. + The user instance data given when was called. + The number of bytes written. + Notes: + In order to use this default output WASAPI callback (playback), you need to make sure that you use this callback only with WASAPI output ( must be ). + Furthermore the following should be considered: If the underlying stream channel is at the end (all data was decoded), + this callback does NOT automatically stop WASAPI via . + So you need to do that by yourself (if you whish to save some performance), e.g. setup a BASS_SYNC_END on the . + If the underlying returns less data, than requested the WASAPI output buffer will be filled with 0's (silence). + Internally will be called on the underlying to request sample data, before the sample data is send to the WASAPI output. + If you intend to overload this callback in a derive implementation make sure to call the base method to not loose any functionatily. + + + + + Provides a ready made callback procedure which might be used for WASAPI input. + + The pointer to the buffer containing the sample data. Will always be floating point! + The number of bytes to process. + The user instance data given when was called. + Will always return 0 here (as it is ignored with input channels). + + To receive the recorded sample data you might use the and set up a DSP on it. + If you intend to overload this callback in a derive implementation make sure to call the base method to not loose any functionatily. + + + + + Gets the currently being used by the Wasapi handler. + + + + + Returns , if the WASAPI handler is used with a WASAPI input device (capture or loopback endpoint). + + + + + Returns , if the WASAPI handler is used in exclusive mode - else shared mode is used. + + + Exclusive mode: The device can only be used exclusivly by the application - which allows greater precision and lets you choose the output sample rate. + Shared mode: The device can be shared by multiple applications. Enforces to use the default sample rate, number of channels and format. + + + + + Returns , if the WASAPI handler uses session volume control - else device volume mode is used. + + + When used with shared mode output, session volume limits the effect of and to the current process; other users of the device are unaffected. + Session volume has no effect on exclusive mode output, and maps to the device volume with input devices (so does affect other users). + + + + + Returns the WASAPI device (endpoint) being used by the Wasapi handler. + + + + + Gets the actual sample rate in Hz which is being used. + + + Depending if you use the Wasapi device in exclusive or shared mode the actual sample rate might be different from the sample rate requested. + In exclusive mode: The sample rate as specified in the constructor will be used. + In shared mode: The default sample rate as specified in the mixer control panel will always be used. + + + + + Gets the actual number of channels being used with the . + + + Depending if you use the Wasapi device in exclusive or shared mode the actual number of channels might be different from the number of channels requested. + In exclusive mode: The maximum available number of channels will always be used. + In shared mode: The default number of channels as specified in the mixer control panel will always be used. + + + + + Gets the actual buffer length (in seconds) being used with the . + + + + + Gets the actual update period (in seconds) being used with the . + + + + + Gets the internal mixer being used with this WASAPI handler (when used with an output device). + + + As WASAPI might require resampling or the used number of channels might not always match the requested number of channels + an internal mixer stream is always created to perform these tasks. + + + + + Gets the BASS output channel handle which is used with this WASAPI input handler in case of full-duplex monitoring. + + + You must call the method in order to use this output channel. + + + + + Gets or Sets the volume of the channels between 0 (silent) and 1 (full). + + + The volume level ranges from 0 (silent) to 1 (normal) or above 1 to amplify the sound. + + + + + Gets or Sets the panning of the channels between -1 (left) to +1 (right), 0=centered. + + Setting the panning uses the property in order to calculate the individual channel volume. + E.g. if you set the panning to -0.7 at a volume of 1.0: chan1-volume (left) = 0.3, chan2-volume (right) = 1.0. + The panning value ranges from -1 (left) to 0 (center) to +1 (right). + In case of multi-channel (not stereo, is greater than 2) the left/right positions are interleaved between the additional channels. + + + + + Gets or Sets the volume of the between 0 (silent) and 1 (full). + + Whereas the and the properties directly effect the internally used channel volume, + this property effects the global WASAPI device volume setting (which might be shared among other applications). + The volume level ranges from 0 (silent) to 1 (normal) or above 1 to amplify the sound. + + + + + Gets or Sets the mute status of the . + + + + + Returns an input channel which allows you to retrieve the recorded sample data and/or apply any DSP/FX on Wasapi input. + + When you are using WASAPI with input ( must return ) and have set the property to + you might use this channel to setup any DSP/FX to be applied to the Wasapi input or just retrieve the recorded sample data. + Any DSP/FX set on this channel will also be passed through to the output, if you are using . + As the InputChannel is a dummy custom decoding stream you can not call directly on it in order to directly get the sample data; + nor can you use it directly as a source stream for any (mixer)output! + Instead use a via to retrieve the sample data. + Note: However, you might independently set any DSP/FX on the full-duplex output using the instead. + + + + + Enables the use of the channel with WASAPI input (which is the default for Wasapi input). + + When you are using WASAPI with input ( must return ) and set this property to + you might use the to setup any DSP/FX to be applied to the Wasapi input or retrieve the recorded sample data. + Any DSP/FX set on this channel will also be passed through to the output, if you are using . + Note: However, you might independently set any DSP/FX on the full-duplex output using the instead. + + + + + Returns , if the WASAPI handler is used with an WASAPI input device and the full-duplex option was set via . + + + + + Gets or Sets the bypass flag for full-duplex WASAPI output processing (default is ). + + If this property is set to any full-duplex output processing is bypassed. + When setting this property to prior to creating a full-duplex via the method this enables you to start full-duplex without processing the output yet. + Setting this property to will start the full-duplex output processing. + This flag will automatically set back to when calling . + + + + + Event handler used to notify that an Wasapi handler notification event (sync) has occurred. + + + The contains a which allows you to react to a possible sync scenarios. + + + + + Definition of the event handler. + + + This definition complies with the .NET Framework's standard for event handlers. + The sender is always set to the object instance that raised the event. + + + + + EventArgs class to be passed as the second parameter of a event handler. + + + This class provides all the information relevant to an event which might occur to a class. + + + + + Initializes a new instance of the BassWasapiHandlerEventArgs class by initializing all of its properties. + + The type of event which occurred (see ). + Some data which should be passed along with the notification event. + + + + Gets the type of sync which occurred. + + + + + Gets the data which was passed along with the event. + + + + + Types of event that has occurred with the class. + + + A variable of this type is passed inside the object + for the event. + + + + + The Wasapi source is stalled. + data: the source stream channel which was stalled. + + + + + The Wasapi source is resumed. + data: the source stream channel which was resumed. + + + + + BASS.NET API wrapper for BASS_ALAC.DLL + Requires: bass_alac.dll - Apple Lossless Audio Codec (ALAC) Add-On - available @ www.un4seen.com. + + + BASS_ALAC is an extension to the BASS audio library, enabling the playback of ALAC files. + ALAC is an audio codec developed by Apple Computer. It is not a variant of AAC, but a totally new lossless format which is usually wrapped into an MP4 or MOV container. The Apple Lossless Encoder was introduced as a component of QuickTime 6.5.1 on April 28th, 2004 and thus as a feature of iTunes 4.5. + The ALAC format is used in the same way as any of the built-in BASS stream formats. Simply call to load the add-on into BASS and benefit the usage of the standard sample/stream/user functions, or call the /User functions. + More information can be found on www.dolby.com. + + + + + NOT used - all members are static! + + + + + + + + + + + + + + + + Creates a sample stream from a Apple Lossless Audio file. + This overload implements UNICODE filenames. The BASS_UNICODE flag will be added automatically, since all .Net strings are always unicode. + + Filename for which a stream should be created. + File offset to begin streaming from. + Data length... 0 = use all data up to the end of the file. + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + + + + + + + + + + + + Creates a sample stream from a Apple Lossless Audio memory IntPtr. + This overload implements streaming from memory. + + An unmanaged pointer to the memory location as an IntPtr. + Offset to begin streaming from (unused for memory streams, set to 0). + Data length (needs to be set to the length of the memory streams in bytes which should be played). + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + Creates a sample stream from a Apple Lossless Audio file via a user callback function. + + File system to use: see . + Any combination of these flags: see . + The user defined file functions (see ). + User instance data to pass to the callback functions. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + See . + + + + Supported file extensions of the bass_alac.dll + + + + + Supported file format name of the bass_alac.dll + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + The disadvantage of this method is, that the standard plugin support for is not working - so you would need to use the native add-on methods! + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + BASS.NET API wrapper for BASS_TTA.DLL + Requires: bass_tta.dll - The True Audio Codec (TTA) Add-On - available @ www.un4seen.com. + + + BASS_TTA is an extension to the BASS audio library, enabling the playing of TTA (The True Audio Codec) encoded files. TTA is a free, simple, realtime lossless audio compressor based on adaptive prognostic filters. The codec was built to offer adequate compression levels while maintaining high operation speeds. + The True Audio format is used in the same way as any of the built-in BASS stream formats. Simply call to load the add-on into BASS and benefit the usage of the standard sample/stream/user functions, or call the or User functions. + More information can be found on www.true-audio.com. + + + + + NOT used - all members are static! + + + + + + + + + + + + + + + + Creates a sample stream from a True Audio file. + This overload implements Unicode filenames. The BASS_UNICODE flag will be added automatically. + + Filename for which a stream should be created. + File offset to begin streaming from. + Data length... 0 = use all data up to the end of the file. + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + + + + + + + + + + + + Creates a sample stream from a True Audio memory IntPtr. + This overload implements streaming from memory. + + An unmanaged pointer to the memory location as an IntPtr. + Offset to begin streaming from (unused for memory streams, set to 0). + Data length (needs to be set to the length of the memory streams in bytes which should be played). + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + Creates a sample stream from a True Audio file via a user callback function. + + File system to use: see . + Any combination of these flags: see . + The user defined file functions (see ). + User instance data to pass to the callback functions. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + See . + + + + Supported file extensions of the bass_tta.dll + + + + + Supported file format name of the bass_tta.dll + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + The disadvantage of this method is, that the standard plugin support for is not working - so you would need to use the native add-on methods! + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + Extension methods must be defined in a static class. + + + + + Removes all leading and trailing white-space characters including + ZERO WIDTH SPACE (U+200B) and ZERO WIDTH NO-BREAK SPACE (U+FEFF) + from the current object. + + The string to trim. + The string that remains after all white-space characters are removed from the start and end of the current string. + + + + BASS.NET API wrapper for BASS_MPC.DLL + Requires: bass_mpc.dll - MusePack Audio Codec (MPC) Add-On - available @ www.un4seen.com. + + + BASS_MPC is an extension to the BASS audio library, enabling the playback of MusePack files. + MusePack is an audio compression format with a strong emphasis on high quality. It's not lossless, but it is designed for transparency, so that you won't be able to hear differences between the original lossless file and the much smaller MPC. It is based on the MPEG 1 Layer II algorithms, but has rapidly developed and vastly improved and is now at an advanced stage in which it contains heavily optimized and patentless code. + The MusePack format is used in the same way as any of the built-in BASS stream formats. Simply call to load the add-on into BASS and benefit the usage of the standard sample/stream/user functions, or call the /User functions. + More information can be found on www.musepack.net. + + + + + NOT used - all members are static! + + + + + + + + + + + + + + + + Creates a sample stream from a MusePack Audio file. + This overload implements UNICODE filenames. The BASS_UNICODE flag will be added automatically, since all .Net strings are always unicode. + + Filename for which a stream should be created. + File offset to begin streaming from. + Data length... 0 = use all data up to the end of the file. + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + + + + + + + + + + + + Creates a sample stream from a MusePack Audio memory IntPtr. + This overload implements streaming from memory. + + An unmanaged pointer to the memory location as an IntPtr. + Offset to begin streaming from (unused for memory streams, set to 0). + Data length (needs to be set to the length of the memory streams in bytes which should be played). + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + Creates a sample stream from a MusePack Audio file via a user callback function. + + File system to use: see . + Any combination of these flags: see . + The user defined file function (see ). + User instance data to pass to the callback function. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + See . + + + + + + + + + + + + + + + + + + + + + + + + + + Creates a sample stream from a MPC file on the internet, optionally receiving the downloaded data in a callback. + + URL of the file to stream. Should begin with "http://" or "ftp://". + File position to start streaming from. This is ignored by some servers, specifically when the file length is unknown. + Any combination of these flags: see . + Callback function to receive the file as it is downloaded... = no callback. + User instance data to pass to the callback function. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + Seeking is only possible once the entire file has been downloaded. + + + + + Supported file extensions of the bass_mpc.dll + + + + + Supported file format name of the bass_mpc.dll + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + The disadvantage of this method is, that the standard plugin support for is not working - so you would need to use the native add-on methods! + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + BASS.NET API wrapper for BASSFLAC.DLL + Requires: bassflac.dll - Free Lossless Audio Codec (FLAC) Add-On - available @ www.un4seen.com. + + + BASSFLAC is an extension to the BASS audio library, enabling the playing of FLAC (Free Lossless Audio Codec) encoded files. + The FLAC format is used in very much the same way as any of the built-in BASS stream formats - simply call the FLAC stream creation function instead of the BASS built-in functions. The BASS plugin system (see ) is also supported. + More information can be found on flac.sourceforge.net. + + + + + NOT used - all members are static! + + + + + + + + + + + + + + + + Creates a sample stream from a FLAC file. + This overload implements UNICODE filenames. The BASS_UNICODE flag will be added automatically, since all .Net strings are always unicode. + + Filename for which a stream should be created. + File offset to begin streaming from. + Data length... 0 = use all data up to the end of the file. + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + + + + + + + + + + + + Creates a sample stream from a FLAC memory IntPtr. + This overload implements streaming from memory. + + An unmanaged pointer to the memory location as an IntPtr. + Offset to begin streaming from (unused for memory streams, set to 0). + Data length (needs to be set to the length of the memory streams in bytes which should be played). + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + Creates a sample stream from a FLAC file via a user callback function. + + File system to use: see . + Any combination of these flags: see . + The user defined file functions (see ). + User instance data to pass to the callback functions. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + See . + + + + + + + + + + + + + + + + + + + + + + + + + + Creates a sample stream from a FLAC file on the internet, optionally receiving the downloaded data in a callback. + + URL of the file to stream. Should begin with "http://" or "ftp://". + File position to start streaming from. This is ignored by some servers, specifically when the file length is unknown. + Any combination of these flags: see . + Callback function to receive the file as it is downloaded... = no callback. + User instance data to pass to the callback function. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + Supported file extensions of the bassflac.dll + + + + + Supported file format name of the bassflac.dll + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + The disadvantage of this method is, that the standard plugin support for is not working - so you would need to use the native add-on methods! + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + .NET API wrapper for BASSASIO.DLL + Requires: bassasio.dll - ASIO driver library - available @ www.un4seen.com. + + + BASSASIO is basically a wrapper for ASIO drivers, with the addition of channel joining, format conversion and resampling. + BASSASIO requires a soundcard with ASIO drivers installed. It also makes use of SSE2 and 3DNow optimizations, but is fully functional without them. + BASS is not required by BASSASIO, but BASS can of course be used to decode, apply DSP/FX, etc. + + + + + Current BASSASIO version (without minor revision). + + + + + Base static contructor. + + + + + NOT used - all members are static! + + + + + Sets the character set used in device information text. + + Use Unicode? If FALSE, ANSI is used, else UTF-16 is used. + If successful, then is returned, else is returned. Use to get the error code. + This function determines the character set that is used in the structure and in function calls. + It does not affect ASIO channel names in the and structure. + + + + Retrieves the error code for the most recent BASSASIO function call in the current thread. + + If no error occured during the last BASSASIO function call then BASS_OK is returned, else one of the values is returned. + See the function description for an explanation of what the error code means. + Error codes are stored for each thread. So if you happen to call 2 or more BASSASIO functions at the same time, they will not interfere with eachother's error codes. + + + + + + + + + + + + Retrieves information on an Asio device. + + The device to get the information of... 0 = first. + An instance of the class to store the information at. + If successful, then is returned, else is returned. Use to get the error code. + + This function can be used to enumerate the available Asio devices for a setup dialog. + + + ERROR CODEDescription + BASS_ERROR_DEVICEThe device number specified is invalid. + + + + + List all available devices: + + BASS_ASIO_DEVICEINFO info = new BASS_ASIO_DEVICEINFO(); + for (int n=0; BassAsio.BASS_ASIO_GetDeviceInfo(n, info); n++) + { + Console.WriteLine(info.ToString()); + } + + + Dim n As Integer = 0 + Dim info As New BASS_ASIO_DEVICEINFO() + While (BassAsio.BASS_ASIO_GetDeviceInfo(n, info)) + Console.WriteLine(info.ToString()) + n += 1 + End While + + Or use the method for more convenience. + + + + + Retrieves information on an Asio device. + + The device to get the information of... 0 = first. + If successful, then an instance of the class is returned, else is returned. Use to get the error code. + + This function can be used to enumerate the available Asio devices for a setup dialog. + + + ERROR CODEDescription + BASS_ERROR_DEVICEThe device number specified is invalid. + + + + + + BASS_ASIO_DEVICEINFO info; + for (int n = 0; (info = BassAsio.BASS_ASIO_GetDeviceInfo(n)) != null; n++) + { + ... + } + + + Dim n As Integer = 0 + Dim info As New BASS_ASIO_DEVICEINFO() + While Not (info Is Nothing) + info = BassAsio.BASS_ASIO_GetDeviceDescription(n) + If Not (info Is Nothing) Then + ... + End If + n += 1 + End While + + Or use the method for more convenience. + + + + + Returns all available Asio devices. + + An array of elements representing the available Asio devices. + Uses internally. + + + + Returns the total number of available Asio devices. + + Number of ASIO devices available. + Uses internally. + + + + Sets the device to use for subsequent calls in the current thread. + + The device to use... 0 = first device. + If successful, then is returned, else is returned. Use to get the error code. + + As in BASS, simultaneously using multiple devices is supported in the BASSASIO API via a context switching system - instead of there being an extra "device" parameter in the function calls, the device to be used is set prior to calling the functions. + The device setting is local to the current thread, so calling functions with different devices simultaneously in multiple threads is not a problem. + The device context setting is used by any function that may result in a BASS_ERROR_INIT error (except this function), which is the majority of them. When one if those functions is called, it will check the current thread's device setting, and if no device is selected (or the selected device is not initialized), BASSASIO will automatically select the lowest device that is initialized. + This means that when using a single device, there is no need to use this function - BASSASIO will automatically use the device that's initialized. Even if you free the device, and initialize another, BASSASIO will automatically switch to the one that is initialized. + + + ERROR CODEDescription + BASS_ERROR_DEVICEThe number specified is invalid. + BASS_ERROR_INITThe device has not been initialized. + + + + + Get the sample rate of device 2: + + // select device 2 + BassAsio.BASS_ASIO_SetDevice(2); + // get the sample rate + double rate = BassAsio.BASS_ASIO_GetRate(); + + + ' select device 2 + BassAsio.BASS_ASIO_SetDevice(2) + ' get the sample rate + Dim rate As Double = BassAsio.BASS_ASIO_GetRate() + + + + + + Retrieves the Asio device setting in the current thread. + + If successful, the device number is returned, else -1 is returned. Use to get the error code. + As in BASS, simultaneously using multiple devices is supported in the BASSASIO API via a context switching system - instead of there being an extra "device" parameter in the function calls, the device to be used needs to be set via prior to calling the function. The device setting is local to the current thread, so calling functions with different devices simultaneously in multiple threads is not a problem. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called - there are no initialized devices. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Adds a driver to the device list. + + The driver's class ID. + The filename of the driver. + An optional description of the driver. + If successful, the new device number is returned (which might be used in a subsequent call), else -1 is returned. Use to get the error code. + + A list of installed ASIO drivers is kept in the Windows registry, which is where BASSASIO gets its device list from, + but it is also possible to add unregistered drivers (eg. private drivers) to the list via this function. + If successful, the returned device number can be used in a call to use the driver. + The driver and name strings are expected to be in ANSI form unless Unicode device information has been enabled via BASS_ASIO_SetUnicode, in which case they are expected to be in UTF-16 form + + + ERROR CODEDescription + BASS_ERROR_FILEOPENThe file does not exist. + + + + + + + Initializes an Asio device/driver. + + The device to use... 0 = first device. can be used to get the total number of devices. + Any combination of these flags (see ): + + BASS_ASIO_THREADHost the driver in a dedicated thread, else the current thread. + BASS_ASIO_JOINORDERPlace joined channels in the order in which was called to join them, else place them in numerically ascending order. + + + If the device was successfully initialized, is returned, else is returned. Use to get the error code. + + This function must be successfully called before any input or output can be performed. + The ASIO driver is accessed via a COM object using the single-threaded apartment model, which means that requests to the driver go through the thread that initialized it, so the thread needs to exist as long as the driver remains initialized. + The thread should also have a message queue. If device initializing and releasing from multiple threads is required, or the application does not have a message queue (eg. a console application), then the BASS_ASIO_THREAD flag can be used to have BASSASIO create a dedicated thread to host the ASIO driver. + Simultaneously using multiple devices is supported in the BASSASIO API via a context switching system - instead of there being an extra "device" parameter in the function calls, the device to be used is set prior to calling the functions. is used to switch the current device. + When successful, BASS_ASIO_Init automatically sets the current thread's device to the one that was just initialized. + + + ERROR CODEDescription + BASS_ERROR_DEVICEThe number specified is invalid. + BASS_ERROR_ALREADYA device has already been initialized. You must call before you can initialize again. + BASS_ERROR_DRIVERThe driver couldn't be initialized. + + + + + + + Releases the Asio device/driver. + + If successful, then is returned, else is returned. Use to get the error code. + Make sure to free each Asio device you have initialized with , is used to switch the current device. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + + + + + + + Retrieves the version number of the BASSASIO.DLL that is loaded. + + The BASSASIO version. For example, 0x02040103 (hex), would be version 2.4.1.3. + There is no guarantee that a previous or future version of BASSASIO supports all the BASSASIO functions that you are using, so you should always use this function to make sure the correct version is loaded. + It is safe to assume that future minor revisions (indicated in the LOWORD) will be fully compatible. + You might use the global constant to check the major revision. + + + Checking the major version only: + + if ( Utils.HighWord(BassAsio.BASS_ASIO_GetVersion()) != BassAsio.BASSASIOVERSION ) + { + MessageBox.Show(this, "Wrong BassAsio Version!"); + } + + + If Utils.HighWord(BassAsio.BASS_ASIO_GetVersion()) <> BassAsio.BASSASIOVERSION Then + MessageBox.Show(Me, "Wrong BassAsio Version!") + End If + + Checking for full version "2.4.1.3": + + if (BassAsio.BASS_ASIO_GetVersion() < Utils.MakeLong(0x0103, 0x0204)) + { + MessageBox.Show(this, "Wrong BassAsio Version!"); + } + + + If BassAsio.BASS_ASIO_GetVersion() < Utils.MakeLong(&H103, &H204) Then + MessageBox.Show(Me, "Wrong BassAsio Version!") + End If + + + + + + Retrieves the version of the BASSASIO.DLL that is loaded. + + The number of components to use. The fieldCount ranges from 1 to 4 (major.minor.build.revision). + The BASSASIO version (major.minor.build.revision). + There is no guarantee that a previous or future version of BASSASIO supports all the BASSASIO functions that you are using, so you should always use this function to make sure the correct version is loaded. + It is safe to assume that future minor revisions (indicated in the LOWORD) will be fully compatible. + + + Version expectedVersion = new Version(2, 4); + if (BassAsio.BASS_ASIO_GetVersion(2) < expectedVersion) + { + MessageBox.Show( this, "Wrong BassAsio Version!" ); + } + + + Dim expectedVersion As New Version(2, 4) + If BassAsio.BASS_ASIO_GetVersion(2) < expectedVersion Then + MessageBox.Show(Me, "Wrong BassAsio Version!") + End If + + + + + + Stops the current Asio device. + + If successful, then is returned, else is returned. Use to get the error code. + As in BASS, simultaneously using multiple devices is supported in the BASSASIO API via a context switching system - instead of there being an extra "device" parameter in the function calls, + the device to be used needs to be set via prior to calling the function. + The device setting is local to the current thread, so calling functions with different devices simultaneously in multiple threads is not a problem. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_STARTThe device hasn't been started. + + + + + + + Retrieves information on the Asio device being used. + + An instance of the class to store the information at. + If successful, is returned, else is returned. Use to get the error code. + As in BASS, simultaneously using multiple devices is supported in the BASSASIO API via a context switching system - instead of there being an extra "device" parameter in the function calls, the device to be used needs to be set via prior to calling the function. The device setting is local to the current thread, so calling functions with different devices simultaneously in multiple threads is not a problem. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + + + + + Display the number of inputs and outputs: + + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD); + BASS_ASIO_INFO info = new BASS_ASIO_INFO(); + if ( BassAsio.BASS_ASIO_GetInfo(info) ) + { + Console.WriteLine( info.ToString() ); + } + + + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD) + Dim info As New BASS_ASIO_INFO() + If BassAsio.BASS_ASIO_GetInfo(info) Then + Console.WriteLine(info.ToString()) + End If + + + + + + Retrieves information on the Asio device being used. + + An instance of the class on success - else . + As in BASS, simultaneously using multiple devices is supported in the BASSASIO API via a context switching system - instead of there being an extra "device" parameter in the function calls, the device to be used needs to be set via prior to calling the function. The device setting is local to the current thread, so calling functions with different devices simultaneously in multiple threads is not a problem. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + + + + + Display the number of inputs and outputs of the current Asio device: + + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD); + BASS_ASIO_INFO info = BassAsio.BASS_ASIO_GetInfo(); + if ( info != null ) + { + Console.WriteLine( info.ToString() ); + } + + + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD) + Dim info As BASS_ASIO_INFO = BassAsio.BASS_ASIO_GetInfo() + If Not (info Is Nothing) Then + Console.WriteLine(info.ToString()) + End If + + + + + + Sets the Asio device's sample rate. + + The sample rate. + If succesful, then is returned, else is returned. Use to get the error code. + When it's not possible to set the device to the rate wanted, can be used to overcome that. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILThe sample rate is not supported by the device/drivers. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Set the Asio device and channel sample rate to the same as the underlying BASS decoding stream, in order to save resampling: + + // get the channel info of the decoding stream + BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(streamDecoding); + // set the source rate + BassAsio.BASS_ASIO_ChannelSetRate(false, 0, (double)info.freq); + // try to set the device rate too (saves resampling) + BassAsio.BASS_ASIO_SetRate( (double)info.freq ); + + + ' get the channel info of the decoding stream + Dim info As BASS_CHANNELINFO = Bass.BASS_ChannelGetInfo(streamDecoding) + ' set the source rate + BassAsio.BASS_ASIO_ChannelSetRate(False, 0, CDbl(info.freq)) + ' try to set the device rate too (saves resampling) + BassAsio.BASS_ASIO_SetRate(CDbl(info.freq)) + + + + + + Starts the current Asio device. + + Buffer length in samples... 0 = use current length. + If successful, then is returned, else is returned. Use to get the error code. + Before starting the device, channels must be enabled using . Once started, channels can't be enabled or disabled until the device is stopped, using . + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_ALREADYThe device has already been started. + BASS_ERROR_NOCHANNo channels have been enabled. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + using Un4seen.Bass; + using Un4seen.BassAsio; + ... + Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero); + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD); + ... + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); + if (stream != 0) + { + // now setup ASIO + _myAsioProc = new ASIOPROC(AsioCallback); + // enable 1st output channel...(0=first) + BassAsio.BASS_ASIO_ChannelEnable(false, 0, _myAsioProc, new IntPtr(stream)); + // and join the next channels to it + BassAsio.BASS_ASIO_ChannelJoin(false, 1, 0); + // and start playing it...start output using default buffer/latency + BassAsio.BASS_ASIO_Start(0); + } + ... + private ASIOPROC _myAsioProc; // make it global, so that it can not be removed by the Garbage Collector + private int AsioCallback(bool input, int channel, IntPtr buffer, int length, IntPtr user) + { + // Note: 'user' contains the underlying stream channel (see above) + // We can simply use the bass method to get some data from a decoding channel + // and store it to the asio buffer in the same moment... + return Bass.BASS_ChannelGetData(user.ToInt32(), buffer, length); + } + + + Imports Un4seen.Bass + Imports Un4seen.BassAsio + ... + Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD) + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT) + If stream <> 0 Then + ' now setup ASIO + _myAsioProc = New ASIOPROC(AddressOf AsioCallback) + ' enable 1st output channel...(0=first) + BassAsio.BASS_ASIO_ChannelEnable(False, 0, _myAsioProc, New IntPtr(stream)) + ' and join the next channels to it + BassAsio.BASS_ASIO_ChannelJoin(False, 1, 0) + ' and start playing it...start output using default buffer/latency + BassAsio.BASS_ASIO_Start(0) + End If + ... + Private _myAsioProc As ASIOPROC ' make it global, so that it can not be removed by the Garbage Collector + Private Function AsioCallback(input As Boolean, channel As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Integer + ' Note: 'user' contains the underlying stream channel (see above) + ' We can simply use the bass method to get some data from a decoding channel + ' and store it to the asio buffer in the same moment... + Return Bass.BASS_ChannelGetData(user.ToInt32(), buffer, length) + End Function + + + + + + Checks, if the current Asio device has been started. + + Returns , if the device has been started, else is returned. Use to get the error code. + + + + Displays the current Asio driver's control panel. + + If successful, then is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Retrieves the current Asio device's sample rate. + + If succesful, the sample rate is returned, else -1 is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + + + + + + + Retrieves the latency of input or output channels of the current Asio device + + Get the input latency? =the output latency. + If successful, the latency in samples is returned, else -1 is returned. Use to get the error code. + + The latency is the delay between the sound being recorded and reaching an , in the case of input channels. And the delay between the sample data being fed to an and actually being heard, in the case of output channels. + The latency is dependant on the buffer size, as specified in the call. So the latency should be checked after making that call, not before. + The latency time can by calculated be dividing the sample latency by the device sample rate. When a channel is being resampled, the sample latency will change, but the effective latency time remains constant. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + + + + + Display the input and output latency, in milliseconds: + + // get the sample rate + double rate = BassAsio.BASS_ASIO_GetRate(); + Console.WriteLine("Input Latency = {0} ms", BassAsio.BASS_ASIO_GetLatency(true) * 1000.0 / rate); + Console.WriteLine("Output Latency = {0} ms", BassAsio.BASS_ASIO_GetLatency(false) * 1000.0 / rate); + + + Dim rate As Double = BassAsio.BASS_ASIO_GetRate() + Console.WriteLine("Input Latency = {0} ms", BassAsio.BASS_ASIO_GetLatency(True) * 1000.0 / rate) + Console.WriteLine("Output Latency = {0} ms", BassAsio.BASS_ASIO_GetLatency(False) * 1000.0 / rate) + + + + + + Retrieves the current CPU usage of BASSASIO. + + The BASSASIO CPU usage as a percentage of total CPU time. + This function includes the time taken by the callback functions. + + + + Set the direct input monitoring state. + + The input channel to set the monitoring state of... -1 = all. + The suggested output channel for the monitoring. + Suggested Gain, ranging from 0 to 0x7fffffff (-inf to +12 dB), 0x20000000 equals 0 dB. + Monitoring state... 0 = off, 1 = on. Other settings may be possible depending on the drivers, e.g.: + 0 = input monitoring off. + 1 = input monitoring on. + 2 = playback monitoring off. + 3 = playback monitoring on. + + Suggested Pan, ranging from 0 = left to 0x7fffffff = right (centre should be 0x40000000). + If succesful, then is returned, else is returned. Use to get the error code. + If the hardware does not support patching and mixing a straight 1 to 1 routing is suggested. + The driver should ignore all the information of ASIOMonitor it cannot deal with, usually these might be either or all of output, gain, pan. + Output is the base channel of a stereo channel pair, i.e. output is always an even channel (0,2,4...). + If an odd input channel should be monitored and no panning or output routing can be applied, the driver has to use the next higher output (imply a hard right pan). + Note that the output, gain and pan settings are just suggestions, and may be ignored by the device/driver. + Some cards/drivers might also support direct output monitoring, in such case use the parameter to denote the output channel to monitor and specify an appropriate value. + ADM has originally been based on a mono in - stereo out scheme. Meaning if you need to monitor a stereo input channel pair you need to call this twice, both using the same output value, but using an odd and an even input value. + In such case set the odd input to pan hard left and the even input to pan hard right. + Also note, that if you have channels in-between not activated in ASIO these will not counted. + So if for example channels 3 and 4 are inactive, ADM input 3 is related to the physical input channel 5! + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Sets a notification callback on the ASIO driver. + + User defined notification function... NULL = disable notifications. + User instance data to pass to the callback function. + If succesful, then is returned, else is returned. Use to get the error code. + + A previously set notification callback can be changed (or removed) at any time, by calling this function again. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + + + + + + + Retrieves information on an Asio channel. + + Dealing with an input channel? = an output channel. + The input/output channel number... 0 = first. + An instance of the class to store the information at. + If successful, is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_ILLPARAMThe and combination is invalid. + + + + + Display the information of all channels: + + BASS_ASIO_CHANNELINFO info = new BASS_ASIO_CHANNELINFO(); + int chan = 0; + while (true) + { + if (!BassAsio.BASS_ASIO_ChannelGetInfo(false, chan, info)) + break; + Console.WriteLine( info.ToString() ); + chan++; + } + + + Dim info As New BASS_ASIO_CHANNELINFO() + Dim chan As Integer = 0 + While True + If Not BassAsio.BASS_ASIO_ChannelGetInfo(False, chan, info) Then + Exit While + End If + Console.WriteLine(info.ToString()) + chan += 1 + End While + + + + + + Retrieves information on an Asio channel. + + Dealing with an input channel? = an output channel. + The input/output channel number... 0 = first. + If successful, an instance of the class is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_ILLPARAMThe and combination is invalid. + + + + + Display the information of the first channel: + + BASS_ASIO_CHANNELINFO info = BassAsio.BASS_ASIO_ChannelGetInfo(false, 0); + if (info != null) + { + Console.WriteLine( info.ToString() ); + } + + + Dim info As BASS_ASIO_CHANNELINFO = BassAsio.BASS_ASIO_ChannelGetInfo(False, 0) + If Not (info Is Nothing) Then + Console.WriteLine(info.ToString()) + End If + + + + + + Enable/disable processing of an Asio channel. + + Dealing with an input channel? = an output channel. + The input/output channel number... 0 = first. + The user defined function to process the channel... = disable the channel. + User instance data to pass to the callback function. + If succesful, then is returned, else is returned. Use to get the error code. + + All ASIO channels are mono. Stereo (and above) channels can be formed by joining multiple channels together using . + Use to begin processing the enabled channels. + You might also use this function on an already enabled ASIO channel if you just want to change the which should be used. + However changing the callback procedure to would disable the channel - which is only possible, if the ASIO device is stopped. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_STARTThe device has been started - it needs to be stopped before (dis)enabling channels. + BASS_ERROR_ILLPARAMThe and combination is invalid. + + + + + + using Un4seen.Bass; + using Un4seen.BassAsio; + ... + Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero); + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD); + ... + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); + if (stream != 0) + { + // now setup ASIO + _myAsioProc = new ASIOPROC(AsioCallback); + // enable 1st output channel...(0=first) + BassAsio.BASS_ASIO_ChannelEnable(false, 0, _myAsioProc, new IntPtr(stream)); + // and join the next channels to it + BassAsio.BASS_ASIO_ChannelJoin(false, 1, 0); + // and start playing it...start output using default buffer/latency + BassAsio.BASS_ASIO_Start(0); + } + ... + private ASIOPROC _myAsioProc; // make it global, so that it can not be removed by the Garbage Collector + private int AsioCallback(bool input, int channel, IntPtr buffer, int length, IntPtr user) + { + // Note: 'user' contains the underlying stream channel (see above) + // We can simply use the bass method to get some data from a decoding channel + // and store it to the asio buffer in the same moment... + return Bass.BASS_ChannelGetData(user.ToInt32(), buffer, length); + } + + + Imports Un4seen.Bass + Imports Un4seen.BassAsio + ... + Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD) + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT) + If stream <> 0 Then + ' now setup ASIO + _myAsioProc = New ASIOPROC(AddressOf AsioCallback) + ' enable 1st output channel...(0=first) + BassAsio.BASS_ASIO_ChannelEnable(False, 0, _myAsioProc, New IntPtr(stream)) + ' and join the next channels to it + BassAsio.BASS_ASIO_ChannelJoin(False, 1, 0) + ' and start playing it...start output using default buffer/latency + BassAsio.BASS_ASIO_Start(0) + End If + ... + Private _myAsioProc As ASIOPROC ' make it global, so that it can not be removed by the Garbage Collector + Private Function AsioCallback(input As Boolean, channel As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Integer + ' Note: 'user' contains the underlying stream channel (see above) + ' We can simply use the bass method to get some data from a decoding channel + ' and store it to the asio buffer in the same moment... + Return Bass.BASS_ChannelGetData(user.ToInt32(), buffer, length) + End Function + + + + + + Join a channel to another. + + Dealing with input channels? = output channels. + The input/output channel number... 0 = first. + The channel to join it to... -1 = remove current join. + If succesful, then is returned, else is returned. Use to get the error code. + + All ASIO channels are mono. By joining them, stereo (and above) channels can be formed, making it simpler to process stereo (and above) sample data. + By default, channels can only be joined to preceding channels. For example, channel 1 can be joined to channel 0, but not vice versa. + The BASS_ASIO_JOINORDER flag can be used in the call to remove that restriction. When joining a group of channels, there should be one channel enabled via with the rest joined to it - + do not join a channel to a channel that is itself joined to another channel. Mirror channels, setup using , cannot be joined with. + If a channel has two or more other channels joined to it, then the joined channels will default to being in numerically ascending order in the callback function's sample data unless the BASS_ASIO_JOINORDER flag was used in the call, + in which case they will be in the order in which they were joined via this function. In the latter case, if this function is called on an already joined channel, the channel will be moved to the end of the joined group. + While a channel is joined to another, it automatically takes on the attributes of the other channel - the other channel's settings determine the sample format, the sample rate and whether it is enabled. + The volume setting remains individual though, allowing balance control over the joined channels. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_STARTThe device has been started - it needs to be stopped before (dis)enabling channels. + BASS_ERROR_ILLPARAMThe and combination is invalid. + BASS_ERROR_FORMATIt is not possible to join channels that do not have the same sample format. + + + + + + // enable processing of output channel 0 + BassAsio.BASS_ASIO_ChannelEnable(false, 0, _myAsioProc, 0); + // join channel 1 to it + BassAsio.BASS_ASIO_ChannelJoin(false, 1, 0); + + + ' enable processing of output channel 0 + BassAsio.BASS_ASIO_ChannelEnable(False, 0, _myAsioProc, 0) + ' join channel 1 to it + BassAsio.BASS_ASIO_ChannelJoin(False, 1, 0) + + + + + + Sets a channel's sample format. + + Dealing with an input channel? = an output channel. + The input/output channel number... 0 = first. + The sample format. One of the following (see ): + + BASS_ASIO_FORMAT_16BIT16-bit integer. + BASS_ASIO_FORMAT_24BIT24-bit integer. + BASS_ASIO_FORMAT_32BIT32-bit integer. + BASS_ASIO_FORMAT_FLOAT32-bit floating-point. + + + If succesful, then is returned, else is returned. Use to get the error code. + + The sample format can vary between ASIO devices/drivers, which could mean a lot of extra/duplicate code being required. To avoid that extra work, BASSASIO can automatically convert the sample data, whenever necessary, to/from a format of your choice. + The native format of a channel can be retrieved via . + For performance reasons, it's best not to use 24-bit sample data whenever possible, as 24-bit data requires a bit more processing than the other formats. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_ILLPARAMThe and combination is invalid, or is. + BASS_ERROR_FORMATFormat conversion is not available for the channel's native sample format (please report). + + + + + Set output channel 0 to use floating-point sample data: + + BassAsio.BASS_ASIO_ChannelSetFormat(false, 0, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT); + + + BassAsio.BASS_ASIO_ChannelSetFormat(False, 0, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT) + + + + + + Sets a channel's sample rate. + + Dealing with an input channel? = an output channel. + The input/output channel number... 0 = first. + The sample rate... 0 = device rate. + If succesful, then is returned, else is returned. Use to get the error code. + + For optimal quality and performance, it is best to set the device to the sample rate you want via , but that's not always possible. + Which is where this function and resampling comes into play. 16 point sinc interpolation is used, giving a good blend of sound quality and performance. It is also SSE2 and 3DNow optimized for an extra boost with supporting CPUs. + When a channel's sample rate is the same as the device rate, resampling is bypassed, so there's no unnecessary performance hit. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_ILLPARAMThe and combination is invalid, or is below 0. + BASS_ERROR_FORMATFormat conversion is not available for the channel's native sample format (please report). + + + + + + // set the device rate + BassAsio.BASS_ASIO_SetRate(44100); + // set the channel's rate + BassAsio.BASS_ASIO_ChannelSetRate(false, 0, 44100); + + + ' set the device rate + BassAsio.BASS_ASIO_SetRate(44100) + ' set the channel's rate + BassAsio.BASS_ASIO_ChannelSetRate(False, 0, 44100) + + + + + + Resets the attributes of a channel (or all channels). + + Dealing with an input channel? = an output channel. + The input/output channel number... 0 = first, -1 = all channels. + The attributes to reset. A combination of the following (see ): + + BASS_ASIO_RESET_ENABLEDisable the channel. + BASS_ASIO_RESET_JOINUnjoin the channel. + BASS_ASIO_RESET_PAUSEUnpause the channel. + BASS_ASIO_RESET_FORMATSet the channel's sample format to the native format. + BASS_ASIO_RESET_RATESet the channel's sample rate to the device rate. + BASS_ASIO_RESET_VOLUMESet the channel's volume to normal (1.0). + + + If succesful, then is returned, else is returned. Use to get the error code. + When resetting all channels (channel = -1), the resetting only applies to all channels of the specified type, ie. input or output, not both. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_ILLPARAMThe and combination is invalid, or is. + BASS_ERROR_STARTThe device has been started - it needs to be stopped before disabling or unjoining channels. + + + + + Disable all output channels and remove all joins between them: + + BassAsio.BASS_ASIO_ChannelReset(false, -1, BASSASIOReset.BASS_ASIO_RESET_ENABLE | BASSASIOReset.BASS_ASIO_RESET_JOIN); + + + BassAsio.BASS_ASIO_ChannelReset(False, -1, BASSASIOReset.BASS_ASIO_RESET_ENABLE Or BASSASIOReset.BASS_ASIO_RESET_JOIN); + + + + + + Suspends processing of a channel. + + Dealing with an input channel? = an output channel. + The input/output channel number... 0 = first. + If succesful, then is returned, else is returned. Use to get the error code. + + Channels can only be disabled when the device is stopped. When you want to stop processing only some of the enabled channels, there are few ways that could be done. You could quickly stop the device, disable the unwanted channels, and restart the device. + In the case of output channels, you could fill the channels' buffers with silence (0s) in the . Or you could pause the channels, using this function. + The less channels BASSASIO has to process, the less CPU it'll use, so stopping and restarting the device would be the most efficient, but that could cause a slight break in the sound of the other channels. + Filling the buffers with silence is the least efficient, as BASSASIO will still process the data as if it was "normal", but it does mean that other channels are unaffected. + Pausing is a compromise between the two - the channels will still be enabled, but BASSASIO will bypass any additional processing (resampling/etc) that may normally be required. + Use to resume processing of a paused channel. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_ILLPARAMThe and combination is invalid. + + + + + + + Checks if a channel is enabled for processing. + + Dealing with an input channel? = an output channel. + The input/output channel number... 0 = first. + The return value is one of the folowing (see ): + + BASS_ASIO_ACTIVE_DISABLEDThe channel is not enabled. + BASS_ASIO_ACTIVE_ENABLEDThe channel is enabled. + BASS_ASIO_ACTIVE_PAUSEDThe channel is enabled and paused. + + + + When a channel is joined to another, the status of the other channel is returned, as that is what determines whether the channel is enabled for processing - whether it's been enabled itself is of no consequence while it is joined to another. + For example, if channel B is joined to channel A, and channel A is not enabled, then neither is channel B. + + + + + Retrieves a channel's sample format. + + Dealing with an input channel? = an output channel. + The input/output channel number... 0 = first. + If an error occurs, -1 (BASS_ASIO_FORMAT_UNKNOWN) is returned, use to get the error code. + If successful, one of the following is returned (see ): + + BASS_ASIO_FORMAT_16BIT16-bit integer. + BASS_ASIO_FORMAT_24BIT24-bit integer. + BASS_ASIO_FORMAT_32BIT32-bit integer. + BASS_ASIO_FORMAT_FLOAT32-bit floating-point. + BASS_ASIO_FORMAT_UNKNOWNUnknown format, an error occured. + + + + + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_ILLPARAMThe and combination is invalid. + + + + + + + Retrieves a channel's sample rate. + + Dealing with an input channel? = an output channel. + The input/output channel number... 0 = first. + If succesful, the channel's sample rate is returned (0 = device rate), else -1 is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_ILLPARAMThe and combination is invalid. + + + + + + + Retrieves the level (peak amplitude) of a channel. + + Dealing with an input channel? = an output channel. + The input/output channel number... 0 = first. + If an error occurs, -1 is returned, use to get the error code. + If successful, the level of the channel is returned, ranging from 0 (silent) to 1 (max). If the channel's native sample format is floating-point, it is actually possible for the level to go above 1. + This function measures the level of a single channel, and is not affected by any other channels that are joined with it. + Volume settings made via affect the level reading of output channels, but not input channels. + When an input channel is paused, it is still possible to get its level. Paused output channels will have a level of 0. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_ILLPARAMThe and combination is invalid. + BASS_ERROR_STARTThe device hasn't been started, or the channel isn't enabled. + BASS_ERROR_FORMATLevel retrieval is not supported for the channel's sample format (please report). + + + + + + // get the linear level + float level = BassAsio.BASS_ASIO_ChannelSetVolume(false, 0); + // translate it to logarithmic dB + double db = 20.0 * Math.Log10(level); + + + ' get the linear level + Dim level As Single = BassAsio.BASS_ASIO_ChannelSetVolume(False, 0) + ' translate it to logarithmic dB + Dim db As Double = 20.0 * Math.Log10(level) + + + + + + Enables an output channel, and makes it mirror another channel. + + The output channel number... 0 = first. + Mirroring an input channel? = an output channel. + The channel to mirror. + If succesful, then is returned, else is returned. Use to get the error code. + + This function allows an input or output channel to be duplicated in other output channel. This can be achieved using normal processing, but it's more efficient to let BASSASIO simply copy the data from one channel to another. + Mirror channels can't be joined together to form multi-channel mirrors. Instead, to mirror multiple channels, an individual mirror should be setup for each of them. + After has been called to begin processing, it's not possible to setup new mirror channels, but it is still possible to change the channel that a mirror is mirroring. + When mirroring an output channel that hasn't been enabled, the mirror channel will just produce silence. When mirroring an input channel that hasn't already been enabled, the channel is automatically enabled for processing when is called, so that it can be mirrored. + If the mirror is switched to a disabled input channel once processing has begun, then it will produce silence. + A mirror channel can be made to have a different volume level to the channel that it's mirroring, using . The volume setting is cumulative. + For example, if the mirror channel has a volume setting of 0.5 and the mirrored channel has a volume setting of 0.4, the effective volume of the mirror channel will be 0.2 (0.5 x 0.4). + can be used to disable a mirror channel. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_STARTThe device has been started - it needs to be stopped before enabling channels. + BASS_ERROR_ILLPARAMAt least one of the channels is invalid. + BASS_ERROR_FORMATIt is not possible to mirror channels that do not have the same sample format. + + + + + Enable output channel 0, and mirror it to channel 1 for stereo output: + + using Un4seen.Bass; + using Un4seen.BassAsio; + ... + Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero); + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD); + ... + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, + BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); + if (stream != 0) + { + // now setup ASIO + _myAsioProc = new ASIOPROC(AsioCallback); + // enable 1st output channel...(0=first) + BassAsio.BASS_ASIO_ChannelEnable(false, 0, _myAsioProc, new IntPtr(stream)); + // mirror it to channel 1 + BassAsio.BASS_ASIO_ChannelEnableMirror(1, false, 0); + // and start playing it...start output using default buffer/latency + BassAsio.BASS_ASIO_Start(0); + } + ... + private ASIOPROC _myAsioProc; // make it global, so that it can not be removed by the GC + private int AsioCallback(bool input, int channel, IntPtr buffer, int length, IntPtr user) + { + // Note: 'user' contains the underlying stream channel (see above) + // We can simply use the bass method to get some data from a decoding channel + // and store it to the asio buffer in the same moment... + return Bass.BASS_ChannelGetData(user.ToInt32(), buffer, length); + } + + + Imports Un4seen.Bass + Imports Un4seen.BassAsio + ... + Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD) + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, + BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT) + If stream <> 0 Then + ' now setup ASIO + _myAsioProc = New ASIOPROC(AddressOf AsioCallback) + ' enable 1st output channel...(0=first) + BassAsio.BASS_ASIO_ChannelEnable(False, 0, _myAsioProc, New IntPtr(stream)) + // mirror it to channel 1 + BassAsio.BASS_ASIO_ChannelEnableMirror(1, False, 0) + ' and start playing it...start output using default buffer/latency + BassAsio.BASS_ASIO_Start(0) + End If + ... + Private _myAsioProc As ASIOPROC ' make it global, so that it can not be removed by the GC + Private Function AsioCallback(input As Boolean, channel As Integer, buffer As IntPtr, + length As Integer, user As IntPtr) As Integer + ' Note: 'user' contains the underlying stream channel (see above) + ' We can simply use the bass method to get some data from a decoding channel + ' and store it to the asio buffer in the same moment... + Return Bass.BASS_ChannelGetData(user.ToInt32(), buffer, length) + End Function + + + + + + Sets a channel's volume. + + Dealing with an input channel? = an output channel. + The input/output channel number... 0 = first, -1 = master. + The volume level... 0 (silent)...1.0 (normal). Above 1.0 amplifies the sound. + If succesful, then is returned, else is returned. Use to get the error code. + + + Apart from the master volume (channel = -1), this function applies a volume level to a single channel, and does not affect any other channels that are joined with it. This allows balance control over joined channels, by setting the individual volume levels accordingly. + The volume "curve" is linear, but logarithmic levels can be easily used. See the example below. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_ILLPARAMThe and combination is invalid, or is below 0. + + + + + Set a logarithmic volume level: + + // translate logarithmic dB level to linear + float volume = (float)Math.Pow(10d, db / 20d); + // apply it + BassAsio.BASS_ASIO_ChannelSetVolume(false, 0 , volume); + + + ' translate logarithmic dB level to linear + Dim volume As Single = CSng(Math.Pow(10.0, db / 20.0)) + ' apply it + BassAsio.BASS_ASIO_ChannelSetVolume(False, 0, volume) + + + + + + Retrieves a channel's volume setting. + + Dealing with an input channel? = an output channel. + The input/output channel number... 0 = first, -1 = master. + If successful, the channel's volume setting is returned, else -1 is returned. Use to get the error code. + To set a channel volume use . + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_ILLPARAMThe and combination is invalid. + + + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + Load BASS and BASSWMA from the application's startup path: + + Bass.LoadMe(); + BassWma.LoadMe(); + ... + // when not used anymore... + BassWma.FreeMe(); + Bass.FreeMe(); + + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + Load BASS and BASSWMA from a different directory: + + Bass.LoadMe( @"C:\Development\BASS\_libs" ); + BassWma.LoadMe( @"C:\Development\BASS\_libs" ); + ... + // when not used anymore... + BassWma.FreeMe(); + Bass.FreeMe(); + + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + Initialization flags to be used with + + + + + Host the driver in the current thread. + + + + + Host the driver in a dedicated thread. + + + + + Order joined channels by when they were joined. + + + + + BassAsio sample formats to be used with and . + + + + + Unknown format. Error. + + + + + 16-bit integer. + + + + + 24-bit integer. + + + + + 32-bit integer. + + + + + 32-bit floating-point. + + + + + BassAsio attributes to be used when to reset a channel with . + + + + + Disable the channel. + + + + + Unjoin the channel. + + + + + Unpause the channel. + + + + + Set the channel's sample format to the native format. + + + + + Set the channel's sample rate to the device rate. + + + + + Reset volume to 1.0 + + + + + BassAsio active values return by . + + + + + The channel is not enabled. + + + + + The channel is enabled. + + + + + The channel is enabled and paused. + + + + + BassAsio notify values as used in the . + + + + + The device's sample rate has changed. The new rate is available from . + + + + + The driver has requested a reset/reinitialization; for example, following a change of the default buffer size. This request can be ignored, but if a reinitialization is performed, it should not be done within the callback. + + + + + Used with to retrieve information on an asio device. + + + + + The description of the device. + + + + + The filename of the driver being used. + Further information can be obtained from the file using the GetFileVersionInfo Win32 API function. + + + + + Default constructor. + + + + + A description of the decive info object (name). + + A description of the decive info object (name). + + + + Used with to retrieve information on the current device. + + + + + The name of the device/driver. + + + + + The driver version. + + + + + The number of input channels available. + + + + + The number of output channels available. + + + + + The minimum buffer length, in samples. + + + + + The maximum buffer length, in samples. + + + + + The preferred/default buffer length, in samples. + + + + + The buffer length granularity, that is the smallest possible length change... -1 = the possible buffer lengths increase in powers of 2. + + + + + The flags parameter of the call. + + + + + Default constructor. + + + + + A description of the decive info object (the driver/device name). + + The name of the device/driver. + + + + Used with to retrieve information on the current device. + + + + + The channel's group. + + + + + The channel's sample format, one of the following (see ): + + BASS_ASIO_FORMAT_16BIT16-bit integer. + BASS_ASIO_FORMAT_24BIT24-bit integer. + BASS_ASIO_FORMAT_32BIT32-bit integer. + BASS_ASIO_FORMAT_FLOAT32-bit floating-point. + + + + + + The name of the channel. + + + + + Default constructor. + + + + + A description of the channel info object (name). + + The name of the channel. + + + + User defined ASIO channel callback function (to be used with ). + + Dealing with an input channel? = an output channel. + The input/output channel number... 0 = first. + The pointer to the buffer containing the recorded data (input channel), or in which to put the data to output (output channel). + The number of bytes to process. + The user instance data given when was called. + The number of bytes written (ignored with input channels). + + ASIO is a low latency system, so a channel callback function should obviously be as quick as possible. can be used to monitor that. + When multiple channels are joined together, the sample data of the channels is interleaved. For example, with 2 channels (ie. stereo), the sample data would be arranged as channel 1, channel 2, channel 1, channel 2, channel 1, etc... + When an output channel needs to be empty/silent but still enabled, the channel's function could fill the buffer with 0s to achieve that, but it is more efficient to pause the channel using . + That way, BASSASIO knows it can bypass any additional processing (resampling/etc) that may normally be required, thus saving some CPU. A channel can be paused from within it's own callback function, in which case the buffered data is outputted (if it's an output channel), and the function is not called again until the channel is unpaused. + Do not call these functions from within an ASIO callback: , . + Also, if it's an output channel, and should not be used on the channel being processed by the callback. + Prior to calling this function, BASSASIO will set the thread's device context to the device that the channel belongs to. So when using multiple devices, can be used to determine which device the channel is on. + NOTE: When you pass an instance of a callback delegate to one of the BASS functions, this delegate object will not be reference counted. + This means .NET would not know, that it might still being used by BASS. The Garbage Collector might (re)move the delegate instance, if the variable holding the delegate is not declared as global. + So make sure to always keep your delegate instance in a variable which lives as long as BASS needs it, e.g. use a global variable or member. + + + Streaming a file via BASS to ASIO: + + int stream = Bass.BASS_StreamCreateFile(fileName, 0, 0, + BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); + if (stream != 0) + { + // now setup ASIO + _myAsioProc = new ASIOPROC(AsioCallback); + // get the stream channel info + BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(stream); + // enable 1st output channel...(0=first) + BassAsio.BASS_ASIO_ChannelEnable(false, 0, _myAsioProc, new IntPtr(stream)); + // and join the next channels to it + for (int a=1; a<info.chans; a++) + BassAsio.BASS_ASIO_ChannelJoin(false, a, 0); + // since we joined the channels, the next commands will apply to all channles joined + // so setting the values to the first channels changes them all automatically + // set the source format (float, as the decoding channel is) + BassAsio.BASS_ASIO_ChannelSetFormat(false, 0, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT); + // set the source rate + BassAsio.BASS_ASIO_ChannelSetRate(false, 0, (double)info.freq); + // try to set the device rate too (saves resampling) + BassAsio.BASS_ASIO_SetRate( (double)info.freq ); + // and start playing it...start output using default buffer/latency + BassAsio.BASS_ASIO_Start(0); + } + ... + private ASIOPROC _myAsioProc; // make it global, so that it can not be removed by the GC + private int AsioCallback(bool input, int channel, IntPtr buffer, int length, IntPtr user) + { + // Note: 'user' contains the underlying stream channel (see above) + // We can simply use the bass method to get some data from a decoding channel + // and store it to the asio buffer in the same moment... + return Bass.BASS_ChannelGetData(user.ToInt32(), buffer, length); + } + + + Dim stream As Integer = Bass.BASS_StreamCreateFile(fileName, 0, 0, + BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT) + If stream <> 0 Then + ' now setup ASIO + _myAsioProc = New ASIOPROC(AsioCallback) + ' get the stream channel info + Dim info As BASS_CHANNELINFO = Bass.BASS_ChannelGetInfo(stream) + ' enable 1st output channel...(0=first) + BassAsio.BASS_ASIO_ChannelEnable(False, 0, _myAsioProc, New IntPtr(stream)) + ' and join the next channels to it + Dim a As Integer + For a = 1 To info.chans - 1 + BassAsio.BASS_ASIO_ChannelJoin(False, a, 0) + Next a + ' since we joined the channels, the next commands will apply to all channles joined + ' so setting the values to the first channels changes them all automatically + ' set the source format (float, as the decoding channel is) + BassAsio.BASS_ASIO_ChannelSetFormat(False, 0, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT) + ' set the source rate + BassAsio.BASS_ASIO_ChannelSetRate(False, 0, CDbl(info.freq)) + ' try to set the device rate too (saves resampling) + BassAsio.BASS_ASIO_SetRate(CDbl(info.freq)) + ' and start playing it...start output using default buffer/latency + BassAsio.BASS_ASIO_Start(0) + End If + ... + Private _myAsioProc As ASIOPROC ' make it global, so that it can not be removed by the GC + Private Function AsioCallback(input As Boolean, channel As Integer, + buffer As IntPtr, length As Integer, user As IntPtr) As Integer + ' Note: 'user' contains the underlying stream channel (see above) + ' We can simply use the bass method to get some data from a decoding channel + ' and store it to the asio buffer in the same moment... + Return Bass.BASS_ChannelGetData(user.ToInt32(), buffer, length) + End Function + + Setting up a full-duplex input to output handler: + + private byte[] _fullDuplexAsioBuffer; + private int _numchans = 2; + + private void SetFullDuplex() + { + BASS_ASIO_INFO info = BassAsio.BASS_ASIO_GetInfo(); + _fullDuplexAsioBuffer = new byte[info.bufmax * _numchans * 4]; + ... + } + + private int AsioToAsioFullDuplexCallback(bool input, int channel, IntPtr buffer, int length, IntPtr user) + { + if (input) + { + if (_fullDuplexAsioBuffer.Length < length) + _fullDuplexAsioBuffer = new byte[length]; + Marshal.Copy(buffer, _fullDuplexAsioBuffer, 0, length); + return 0; + } + else + { + if (length > _fullDuplexAsioBuffer.Length) + length = _fullDuplexAsioBuffer.Length; + Marshal.Copy(_fullDuplexAsioBuffer, 0, buffer, length); + return length; + } + } + + + Private _fullDuplexAsioBuffer As Byte() + Private _numchans As Integer = 2 + + Private Sub SetFullDuplex() + Dim info As BASS_ASIO_INFO = BassAsio.BASS_ASIO_GetInfo() + _fullDuplexAsioBuffer = New Byte(info.bufmax * _numchans * 4 - 1) {} + ... + End Sub + + Private Function AsioToAsioFullDuplexCallback(ByVal input As Boolean, ByVal channel As Integer, + ByVal buffer As IntPtr, ByVal length As Integer, + ByVal user As IntPtr) As Integer + If input Then + If _fullDuplexAsioBuffer.Length < length Then + _fullDuplexAsioBuffer = New Byte(length - 1) {} + End If + Marshal.Copy(buffer, _fullDuplexAsioBuffer, 0, length) + Return 0 + Else + If length > _fullDuplexAsioBuffer.Length Then + length = _fullDuplexAsioBuffer.Length + End If + Marshal.Copy(_fullDuplexAsioBuffer, 0, buffer, length) + Return length + End If + End Function + + + + + + User defined notification callback function (to be used with ). + + The notification, one of the following: + + BASS_ASIO_NOTIFY_RATEThe device's sample rate has changed. The new rate is available from . + BASS_ASIO_NOTIFY_RESETThe driver has requested a reset/reinitialization; for example, following a change of the default buffer size. This request can be ignored, but if a reinitialization is performed, it should not be done within the callback. + + + The user instance data given when was called. + + When using multiple devices, can be used to determine which the notification applies to. + + + + + This class provides ready-made members for direct and more simple ASIO usage together with BASS channels. + + + You might use this class for almost all use cases in terms of Asio handling, e.g.: + + Scenario:How-To: + Asio outputA Bass decoding channel or a recording channel feeding Asio output. + Simply use the corresponding output constructor to specify the Asio and as well the to use and you are done. + The , and will automatically be aligned. Use the method to change the underlying bass channel on the fly. + + Asio inputDirectly record from Asio input. + Simply use the corresponding input constructor to specify the Asio , , , and you want to record at. + To retrieve the input sample data use the channel (e.g. setup an own DSP, use it with the or Encoder Framework). + + Asio input, full-duplex to AsioMonitor your Asio input on any Asio output. + To enable full-duplex just call the Asio overload of the method (when done call ). + + Asio input, full-duplex to BASSMonitor your Asio input on any BASS device. + To enable full-duplex just call the bass overload of the method (when done call ). + + DSP/FXYou can set any DSP/FX on either the input and/or the output (full-duplex). + See and for more details. + + In addition to the above this class supports overloading of the default Asio callbacks (, , , ). + + You might use the and properties to easily control your Asio input/output settings. + Asio mirrors are also supported via the and methods. Mirrors have independent and settings. + Asio channels can be paused and resumed at any time by using the method. + To physically start the used Asio device the method might be used. will unjoin, disable and stop the Asio device (if really needed). + Caution: Once you created an instance of this class, the respective ASIO channels are joined and enabled. + The used ASIO channels will NOT be unjoined or disabled automatically when an instance of this class is being disposed by the .Net Garbage Collector! + Call the method manually to completely free all assigned ASIO channels, including any full-duplex and the mirror options. + However, calling will not stop the Asio device - this has to be done manually in any case (e.g. by calling )! + Note: This class internally uses , so you need to provide the native BASS.dll as well when using this class. + The , , and callbacks are virtual methods + which might be overloaded if you want to derive your own ASIO handler with any special callback handling. + + + Automatic use of the BassAsioHandler (a Bass channel is feeding Asio output): + + private BassAsioHandler _asio; + ... + // not playing anything via BASS, so don't need an update thread + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0); + // setup BASS - "no sound" device but 48000 (default for ASIO) + Bass.BASS_Init(0, 48000, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero); + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD); + ... + int stream = Bass.BASS_StreamCreateFile(fileName, 0, 0, + BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); + if (stream != 0) + { + // assign ASIO output to the first device and channel + // and assume the ASIO format, samplerate and number of channels from the BASS stream + _asio = new BassAsioHandler(0, 0, stream); + // start ASIO + _asio.Start(0); + } + + + Private _asio As BassAsioHandler + ... + ' not playing anything via BASS, so don't need an update thread + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0) + ' setup BASS - "no sound" device but 48000 (default for ASIO) + Bass.BASS_Init(0, 48000, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD) + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile(fileName, 0, 0, + BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT) + If stream <> 0 Then + ' assign ASIO output to the first device and channel + ' and assume the ASIO format, samplerate and number of channels from the BASS stream + _asio = New BassAsioHandler(0, 0, stream) + ' start ASIO + _asio.Start(0) + End If + + Automatic use of the BassAsioHandler (Asio recording input, Asio full-duplex output): + + private BassAsioHandler _asio; + ... + // not playing anything via BASS, so don't need an update thread + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0); + // setup BASS - "no sound" device but 48000 (default for ASIO) + Bass.BASS_Init(0, 48000, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero); + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD); + ... + // assign ASIO input to the first device and channel (stereo, 32-bit float, 48kHz) + _asio = new BassAsioHandler(true, 0, 0, 2, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT, 48000); + // set the full-duplex option to the first ASIO output device and channel + // the ASIO output format will aways be the same as the input for full-duplex + _asio.SetFullDuplex(0, 0); + // start ASIO + _asio.Start(0); + ... + // when you want to disbale all associated channels, call: + _asio.Dispose(); + + + Private _asio As BassAsioHandler + ... + ' not playing anything via BASS, so don't need an update thread + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0) + ' setup BASS - "no sound" device but 48000 (default for ASIO) + Bass.BASS_Init(0, 48000, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD) + ... + ' assign ASIO input to the first device and channel (stereo, 32-bit float, 48kHz) + _asio = New BassAsioHandler(True, 0, 0, 2, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT, 48000) + ' set the full-duplex option to the first ASIO output device and channel + ' the ASIO output format will aways be the same as the input for full-duplex + _asio.SetFullDuplex(0, 0) + ' start ASIO + _asio.Start(0) + ... + ' when you want to disbale all associated channels, call: + _asio.Dispose() + + + + + + Gets or Sets, if the driver should be hosted in a dedicated thread. + + + + + Default constructor - leaving all defaults and not assigning any ASIO channel. + + Use this constructor, if you for example want to leverage the , or callback methods. + In this case make sure to also set the property, since this member will be used in the mentioned default callback procedures. + Also make sure, that the ASIO channel use will use matches the samplerate and the format of the ! + + Manual use of the BassAsioHandler: + + private ASIOPROC _myAsioProc; + private BassAsioHandler _asio; + ... + // not playing anything via BASS, so don't need an update thread + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0); + // setup BASS - "no sound" device but 48000 (default for ASIO) + Bass.BASS_Init(0, 48000, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero); + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD); + ... + int stream = Bass.BASS_StreamCreateFile(fileName, 0, 0, + BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); + if (stream != 0) + { + _asio = new BassAsioHandler(); + _asio.OutputChannel = stream; + + // now setup ASIO manually + _myAsioProc = new ASIOPROC(_asio.BassToAsioOutputCallback); + // get the stream channel info + BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(stream); + // enable 1st output channel...(0=first) + BassAsio.BASS_ASIO_ChannelEnable(false, 0, _myAsioProc, stream); + // and join the next channels to it + for (int a=1; a<info.chans; a++) + BassAsio.BASS_ASIO_ChannelJoin(false, a, 0); + // since we joined the channels, the next commands will apply to all channles joined + // so setting the values to the first channels changes them all automatically + // set the source format (float, as the decoding channel is) + BassAsio.BASS_ASIO_ChannelSetFormat(false, 0, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT); + // set the source rate + BassAsio.BASS_ASIO_ChannelSetRate(false, 0, (double)info.freq); + // try to set the device rate too (saves resampling) + BassAsio.BASS_ASIO_SetRate( (double)info.freq ); + // and start playing it...start output using default buffer/latency + _asio.Start(0); + } + + + Private _myAsioProc As ASIOPROC + Private _asio As BassAsioHandler + ... + ' not playing anything via BASS, so don't need an update thread + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0) + ' setup BASS - "no sound" device but 48000 (default for ASIO) + Bass.BASS_Init(0, 48000, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD) + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile(fileName, 0, 0, + BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT) + If stream <> 0 Then + _asio = New BassAsioHandler() + _asio.OutputChannel = stream + + ' now setup ASIO manually + _myAsioProc = New ASIOPROC(AddressOf _asio.BassToAsioOutputCallback) + ' get the stream channel info + Dim info As BASS_CHANNELINFO = Bass.BASS_ChannelGetInfo(stream) + ' enable 1st output channel...(0=first) + BassAsio.BASS_ASIO_ChannelEnable(False, 0, _myAsioProc, stream) + ' and join the next channels to it + Dim a As Integer + For a = 1 To info.chans - 1 + BassAsio.BASS_ASIO_ChannelJoin(False, a, 0) + Next a + ' since we joined the channels, the next commands will apply to all channles joined + ' so setting the values to the first channels changes them all automatically + ' set the source format (float, as the decoding channel is) + BassAsio.BASS_ASIO_ChannelSetFormat(False, 0, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT) + ' set the source rate + BassAsio.BASS_ASIO_ChannelSetRate(False, 0, CDbl(info.freq)) + ' try to set the device rate too (saves resampling) + BassAsio.BASS_ASIO_SetRate(CDbl(info.freq)) + ' and start playing it...start output using default buffer/latency + _asio.Start(0) + End If + + + + + + Creates an instance of the ASIO handler - initializing and enabling the given ASIO device and channel. + + Dealing with an input channel? =an output channel, = an input channel (in which case the will automatically set to , so that you can use the .). + The ASIO device to use (0=first). + The ASIO input/output channel number (0=first). + The total number of ASIO channels to use (following channels will be joined - e.g. 2 for stereo). + The ASIO sample format to use for the channel(s) - see for details. + The desired samplerate to use with the channel(s) - use or -1 if uncertain and to prevent resampling. + If the ASIO device samplerate could not be set to the desired samplerate, the device's current samplerate will be taken instead. + + Use this constructor for either manual Asio handler use or for Asio input recording. + The following will be done internally: + 1. The ASIO device will be initialized (if already done, the ASIO device will just be set). + 2. The ASIO device's samplerate will be set to the given - if the ASIO device samplerate could not be changed the device's current samplerate will be taken! + 3a. If input: use the as the internal . Also will be set to , so that you can use the to retrieve the recorded sample data. + 3b. If output: use the as the internal . + 4. If the ASIO device was already started, it will be stopped when necessary (only if the ASIO channel has not yet been enabled). The device will be started again. + 5. Enable and join the given with the following channels according to the total . + 6. Set the ASIO channel format and samplerate according to the given and . + Note: If the given has already been enabled, it will be reused and not enabled and joined again! + This means, that the channel number of the already joined channel will not be changed as well and might not match to the channel number of the given parameter. + + + Automatic use of the BassAsioHandler (Asio recording input, Asio full-duplex output): + + private BassAsioHandler _asio; + ... + // not playing anything via BASS, so don't need an update thread + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0); + // setup BASS - "no sound" device but 48000 (default for ASIO) + Bass.BASS_Init(0, 48000, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero); + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD); + ... + // assign ASIO input to the first device and channel (stereo, 32-bit float, 48kHz) + _asio = new BassAsioHandler(true, 0, 0, 2, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT, 48000); + // set the full-duplex option to the first ASIO output device and channel + // the ASIO output format will aways be the same as the input for full-duplex + _asio.SetFullDuplex(0, 0); + // start ASIO + _asio.Start(0); + ... + // when you want to disbale all associated channels, call: + _asio.Dispose(); + + + Private _asio As BassAsioHandler + ... + ' not playing anything via BASS, so don't need an update thread + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0) + ' setup BASS - "no sound" device but 48000 (default for ASIO) + Bass.BASS_Init(0, 48000, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD) + ... + ' assign ASIO input to the first device and channel (stereo, 32-bit float, 48kHz) + _asio = New BassAsioHandler(True, 0, 0, 2, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT, 48000) + ' set the full-duplex option to the first ASIO output device and channel + ' the ASIO output format will aways be the same as the input for full-duplex + _asio.SetFullDuplex(0, 0) + ' start ASIO + _asio.Start(0) + ... + ' when you want to disbale all associated channels, call: + _asio.Dispose() + + + + + + Creates an instance of the ASIO handler for output - initializing and enabling the given ASIO device and channel according to the Bass stream. + + The ASIO device to use (0=first). + The ASIO output channel number (0=first). + The BASS channel handle which should be used with ASIO output (must be a decoding or recording channel and must be either 16-bit or 32-bit). + + Use this constructor for automatic Asio output using either a decoding or recording . + The following will be done internally: + 1. The ASIO device will be initialized (if already done, the ASIO device will just be set). + 2. The samplerate, format and number of channels will be determined from the given . + 3. The ASIO device will be set to the determined samplerate. If this fails, the current ASIO samplerate will not be changed. In this case it might happen (if ASIO device samplerate and stream samplerate are different) that the ASIO output needs to be resampled. + 4. Output: use the as the internal . + 4. Enable and join the given with the following channels according to the total number of chans of the . + 5. Set the format and samplerate according to the given samplerate and format of the . + Note: If the given has already been enabled, it will be reused and not enabled and joined again! + This means, that the channel number of the already joined channel will not be changed as well and might not match to the channel number of the given . + + Invalid channel: must be a valid BASS channel (either decoding or recording). + + Automatic use of the BassAsioHandler (Asio output from a Bass stream): + + private BassAsioHandler _asio; + ... + // not playing anything via BASS, so don't need an update thread + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0); + // setup BASS - "no sound" device but 48000 (default for ASIO) + Bass.BASS_Init(0, 48000, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero); + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD); + ... + int stream = Bass.BASS_StreamCreateFile(fileName, 0, 0, + BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); + if (stream != 0) + { + // assign ASIO output to the first device and channel + // and assume the ASIO format, samplerate and number of channels from the BASS stream + _asio = new BassAsioHandler(0, 0, stream); + // start ASIO + _asio.Start(0); + } + + + Private _asio As BassAsioHandler + ... + ' not playing anything via BASS, so don't need an update thread + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0) + ' setup BASS - "no sound" device but 48000 (default for ASIO) + Bass.BASS_Init(0, 48000, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) + BassAsio.BASS_ASIO_Init(0, BASSASIOInit.BASS_ASIO_THREAD) + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile(fileName, 0, 0, + BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT) + If stream <> 0 Then + ' assign ASIO output to the first device and channel + ' and assume the ASIO format, samplerate and number of channels from the BASS stream + _asio = New BassAsioHandler(0, 0, stream) + ' start ASIO + _asio.Start(0) + End If + + + + + + Disposes an instance of this class also unjoining and disabling all used ASIO channels. + + The used ASIO channel(s) will be unjoined and disabled! This means, that the ASIO device needs to stopped for a short moment! + Caution: Once you created an instance of this class, the respective ASIO channel(s) are joined and enabled. + Calling this method will automatically unjoin and disable the used ASIO channels as well as the full-duplex and mirror channels will be removed and disabled! + If you want to prevent this little break in the ASIO device (since the ASIO device needs to be stopped for a short moment) make sure this method is never called during the device is started. + Also if you want to leave all ASIO channels enabled (even if you do not need this instance anymore) do NOT call this method! In such case you might call and manually if needed, + and you might also call or manually. + + + + + Finalization code. + + This destructor will run only if the Dispose method does not get called. + It gives your base class the opportunity to finalize. Do not provide destructors in types derived from this class. + + + + Starts the Asio . + + Buffer length in samples... 0 = use current length. + If successful, then is returned, else is returned. Use to get the error code. + Calls internally on the being used by the Asio handler (if not already started). + If you need to stop the Asio device you might call . + + + + + Stops the Asio . + + If successful, then is returned, else is returned. Use to get the error code. + Calls internally on the being used by the Asio handler (if not already stopped). + If you need to start the Asio device you might call . + Caution: If you are using multiple instances of the which use the same Asio calling this method impacts the other instances as well, + as the Asio itself is being stopped. In such case you might call to unjoin and disable only the ASIO channels used by this instance. + + + + + Starts the Asio . + + Buffer length in samples... 0 = use current length. + If successful, then is returned, else is returned. Use to get the error code. + Calls internally on the being used by the Asio handler (if not already stopped and if used). + If you need to stop the full-duplex Asio device you might call . + + + + + Stops the Asio . + + If successful, then is returned, else is returned. Use to get the error code. + Calls internally on the being used by the Asio handler (if not already stopped and if used). + If you need to start the full-duplex Asio device you might call . + Caution: If you are using multiple instances of the which use the same Asio calling this method impacts the other instances as well, + as the Asio itself is being stopped. In such case you might call to stop the full-duplex channels used by this instance + or consider calling to disable and remove the full-duplex option. + + + + + Pauses or Unpauses the ASIO (s) being used. + + if you want to pause the ASIO channel(s) - if you want to unpause. + On success is returned, else will be returned (use to retrieve the error code). + When in full-duplex input mode (see ) the related AISO input as well as the ASIO output channel(s) will be (un)paused. + + + + Pauses or Unpauses the (s) being used. + + if you want to pause the ASIO channel(s) - if you want to unpause. + On success is returned, else will be returned (use to retrieve the error code). + + + + Assigns a (new) BASS channel handle for ASIO output. + + The BASS channel handle which should be used with ASIO output (should be a decoding or recording channel and must be either 16-bit or 32-bit) - or 0 (zero) to remove an existing . + On success is returned, else will be returned (use to retrieve the error code). + + The following will be done internally: + 1. The current ASIO channel will be paused (if already enabled). + 2. The samplerate, format and number of channels will be determined from the given . + 3. The ASIO device will be set to the determined samplerate. If this fails, the current ASIO samplerate will not be changed. In this case it might happen (if ASIO device samplerate and stream samplerate are different) that the ASIO output needs to be resampled. + 4a. ASIO enabled: use the as the internal , if the ASIO was already enabled and joined, it will not be changed. + 4b. ASIO disabled: Enable and join the given Asio with the following channels according to the total number of chans of the . + 5. Set the ASIO format and samplerate according to the given samplerate and format of the . + 6. The current ASIO channel will be unpaused (if it was paused before). + This method can not be used with ASIO input (see ). It will immediately return with no effect. + Tyically a decoding channel must be used, but a recording channel will also work, since the interal ASIO procedure being used simply calls to pull the sample data from the as needed and reqested by ASIO. + + Invalid channel: must be a valid BASS channel (either decoding or recording). + + Automatic use of the BassAsioHandler (output): + + private BassAsioHandler _asio; + ... + int stream = Bass.BASS_StreamCreateFile(fileName, 0, 0, + BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); + if (stream != 0) + { + // assign ASIO output to the first device and channel + // and assume the ASIO format, samplerate and number of channels from the BASS stream + _asio = new BassAsioHandler(0, 0, stream); + // start ASIO + BassAsio.BASS_ASIO_Start(0); + } + ... + // assign a new channel to ASIO output + Bass.BASS_StreamFree(stream); + int newStream = Bass.BASS_StreamCreateFile(newFileName, 0, 0, + BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT ); + _asio.AssignOutputChannel(newStream); + + + Private _asio As BassAsioHandler + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile(fileName, 0, 0, + BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT) + If stream <> 0 Then + ' assign ASIO output to the first device and channel + ' and assume the ASIO format, samplerate and number of channels from the BASS stream + _asio = New BassAsioHandler(0, 0, stream) + ' start ASIO + BassAsio.BASS_ASIO_Start(0) + End If + ... + ' assign a new channel to ASIO output + Bass.BASS_StreamFree(stream) + Dim newStream As Integer = Bass.BASS_StreamCreateFile(newFileName, 0, 0, + BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT) + _asio.AssignOutputChannel(newStream) + + + + + + Sets the full-duplex option for ASIO input using the given ASIO output device and channel. + + The ASIO output device which should be used for full-duplex monitoring. + The ASIO output channel which should be used for full-duplex monitoring. + On success is returned, else will be returned (use to retrieve the error code). + + The full-duplex options is only available on input channels. However even a full-duplex output channel on a different ASIO device might even be used. + If you want to mirror an ASIO input channel to an output channel on the same device, you might might also use the method instead, which is more efficient in such case. + The following will be done internally: + 1. The ASIO input will be used (and enabled and joined, only if not enabled yet). + 2. A custom dummy decoding stream (see ) will be created with the as the internal . + 3. The samplerate, format and number of channels will not be changed for ASIO input, since this will be used as already specified in the constructor. + 4. The ASIO output will only be stopped, if already started and the has not yet been enabled - it will automatically be started again if needed. + 5. The ASIO output device will be set to the same samplerate as the ASIO input. If this fails, the current ASIO samplerate will not be changed. In this case it might happen (if ASIO device samplerate and input samplerate are different) that the ASIO output needs to be resampled. + 6. The ASIO output will be enabled and joined (only if not already enabled) as well as the format and samplerate will be set. All according to the given number of channels, samplerate and format of the ASIO input . + This method can not be used with ASIO output (see ). It will immediately return with no effect. + To disable and remove the full-duplex option call . + The full-duplex ASIO output is provided by an internal custom dummy decoding stream . You might use this stream to set up DSPs or FX on it so that these are applied on the ASIO output. + You might bypass any full-duplex output procesing by setting the property to . + + + Automatic use of the BassAsioHandler (Asio recording input, full-duplex Asio output): + + private BassAsioHandler _asio; + private DSP_PeakLevelMeter _plm; + ... + // assign ASIO input to the first device and channel (stereo, 32-bit float, 48kHz) + _asio = new BassAsioHandler(true, 0, 0, 2, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT, 48000); + // set the full-duplex option to the first ASIO output device and channel + // the ASIO output format will always be the same as the input for full-duplex + _asio.SetFullDuplex(0, 0); + + // set up a ready-made DSP (here the PeakLevelMeter) on the full-duplex channel + _plm = new DSP_PeakLevelMeter(_asio.OutputChannel, 0); + _plm.UpdateTime = 0.1f; // 100ms + _plm.CalcRMS = true; + _plm.Notification += new EventHandler(OnPlmNotification); + + // start ASIO + BassAsio.BASS_ASIO_Start(0); + ... + private void OnPlmNotification(object sender, EventArgs e) + { + if (_plm == null) + return; + // sender will be the DSP_PeakLevelMeter instance + // you could also access it via: DSP_PeakLevelMeter p = (DSP_PeakLevelMeter)sender; + this.progressBarPeak1Left.Value = _plm.LevelL; + this.progressBarPeak1Right.Value = _plm.LevelR; + this.labelLevel1.Text = String.Format( "RMS: {0:#00.0} dB AVG: {1:#00.0} dB Peak: {2:#00.0} dB", + _plm.RMS_dBV, _plm.AVG_dBV, Math.Max(_plm.PeakHoldLevelL_dBV, _plm.PeakHoldLevelR_dBV) ); + } + + + Private _asio As BassAsioHandler + Private _plm As DSP_PeakLevelMeter + ... + ' assign ASIO input to the first device and channel (stereo, 32-bit float, 48kHz) + _asio = New BassAsioHandler(True, 0, 0, 2, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT, 48000) + ' set the full-duplex option to the first ASIO output device and channel + ' the ASIO output format will always be the same as the input for full-duplex + _asio.SetFullDuplex(0, 0) + + ' set up a ready-made DSP (here the PeakLevelMeter) on the full-duplex channel + _plm = New DSP_PeakLevelMeter(_asio.OutputChannel, 0) + _plm.UpdateTime = 0.1F ' 100ms + _plm.CalcRMS = True + AddHandler _plm.Notification, AddressOf OnPlmNotification + + ' start ASIO + BassAsio.BASS_ASIO_Start(0) + ... + Private Sub OnPlmNotification(sender As Object, e As EventArgs) + If _plm Is Nothing Then + Return + End If + ' sender will be the DSP_PeakLevelMeter instance + ' you could also access it via: + ' Dim p As DSP_PeakLevelMeter = CType(sender, DSP_PeakLevelMeter) + Me.progressBarPeak1Left.Value = _plm.LevelL + Me.progressBarPeak1Right.Value = _plm.LevelR + Me.labelLevel1.Text = [String].Format("RMS: {0:#00.0} dB AVG: {1:#00.0} dB Peak: {2:#00.0} dB", + _plm.RMS_dBV, _plm.AVG_dBV, Math.Max(_plm.PeakHoldLevelL_dBV, _plm.PeakHoldLevelR_dBV)) + End Sub + + + + + + Sets the full-duplex option for ASIO input using the given BASS output device. + + The BASS output device which should be used for full-duplex monitoring. + The optional flags to be used to create the full-duplex monitoring . + Typically only the following flags should be used: BASS_STREAM_DECODE, BASS_SAMPLE_SOFTWARE or BASS_SPEAKER_xxx. + , if the should be (pre)buffered - else . + Prebuffering of sample data is often requied for buffered output to enable a constant playback. So even if you are using a BASS_STREAM_DECODE flag you might need to prebuffer it's data. + + On success is returned, else will be returned (use to retrieve the error code). + + The following will be done internally: + 1. The ASIO input will be used (and enabled and joined, only if not enabled yet). + 2. The BASS output will be used. + 3. A custom push stream (see ) will be created (using the given ) with an internal ASIO callback feeding the stream with the sample data from the input. + 4. The samplerate, format and number of channels will not be changed for ASIO input, since this will be used as already specified in the constructor. + 5. The custom push stream will be started playing (via ) - unless the flag has been specified. + This method can not be used with ASIO output (see ). It will immediately return with no effect. + To disable and remove the full-duplex option call . + The full-duplex BASS output is provided by the internal custom push stream . You might use this stream to set up DSPs or FX on it so that these are applied on the BASS output. + You might bypass any full-duplex output procesing by setting the property to . + You might use the 0 (no-sound) bass device together with the BASS_STREAM_DECODE flag in order to create a custom decoding which might for example be used with an or or + as a source for a mixer channel. + + + Automatic use of the BassAsioHandler (Asio recording input, full-duplex to BASS): + + private BassAsioHandler _asio; + ... + // assign ASIO input to the first device and channel (stereo, 32-bit float, 48kHz) + _asio = new BassAsioHandler(true, 0, 0, 2, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT, 48000); + // set the full-duplex option to the first BASS output device using the rear speakers + // the BASS output format will always be the same as the ASIO input for full-duplex + _asio.SetFullDuplex(1, BASSFlag.BASS_SPEAKER_REAR, true); + + // start ASIO + BassAsio.BASS_ASIO_Start(0); + _asio.ResetFullDuplex(); + + // setup an FX on the full-duplex BASS output + BASS_FXECHO echo = new BASS_FXECHO(); + int fxHandle = Bass.BASS_ChannelSetFX(_asio.OutputChannel, BASSFXType.BASS_FX_ECHO, 0); + echo.Preset_Long(); + // apply the effect parameters + Bass.BASS_FXSetParameters(fxHandle, echo); + + + Private _asio As BassAsioHandler + ... + ' assign ASIO input to the first device and channel (stereo, 32-bit float, 48kHz) + _asio = New BassAsioHandler(True, 0, 0, 2, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT, 48000) + ' set the full-duplex option to the first BASS output device using the rear speakers + ' the BASS output format will always be the same as the ASIO input for full-duplex + _asio.SetFullDuplex(1, BASSFlag.BASS_SPEAKER_REAR, True) + + ' start ASIO + BassAsio.BASS_ASIO_Start(0) + _asio.ResetFullDuplex() + + ' setup an FX on the full-duplex BASS output + Dim echo As New BASS_FXECHO() + Dim fxHandle As Integer = Bass.BASS_ChannelSetFX(_asio.OutputChannel, BASSFXType.BASS_FX_ECHO, 0) + echo.Preset_Long() + ' apply the effect parameters + Bass.BASS_FXSetParameters(fxHandle, echo) + + + + + + Removes the full-duplex option from ASIO input. + + Disable and unjoin the ASIO output channel? =leave them enabled and joined. + On success is returned, else will be returned (use to retrieve the error code). + The full-duplex option must have been set before via . + The following will be done internally: + 1. The ASIO output will be stopped (if already started). + 2. The ASIO output will be disabled and unjoined. + 3. The ASIO output device will be started again (only, if it has been started before). + 4. The ASIO input will be stopped (if already started). + 5. The ASIO input will be disabled. + 6. Any custom dummy decoding stream (see ) will be freed and the will again be used as the internal . + 7. The ASIO input channel will be (re)enabled, the samplerate, format and number of channels will not be changed for ASIO input, since this will be used as already specified in the constructor. + 8. The ASIO input device will be started again (only, if it has been started before). + Note: This method will only disable the if specified in the parameter. + This method can not be used with ASIO output (see ). It will immediately return with no effect. + To enable the full-duplex option again, call . + Note, that this method also resets the property to . + + + Automatic use of the BassAsioHandler (recording input, full-duplex): + + private BassAsioHandler _asio; + ... + // assign ASIO input to the first device and channel (stereo, 32-bit float, 48kHz) + _asio = new BassAsioHandler(true, 0, 0, 2, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT, 48000); + // set the full-duplex option to the first ASIO output device and channel + // the ASIO output format will aways be the same as the input for full-duplex + _asio.SetFullDuplex(0, 0); // first output device and channel + // start ASIO + _asio.Start(0); + ... + // remove the full-duplex option and leave the channel enabled + _asio.RemoveFullDuplex(false); + // but pause the unused output channel + BassAsio.BASS_ASIO_ChannelPause(false, 0); + ... + + + Private _asio As BassAsioHandler + ... + ' assign ASIO input to the first device and channel (stereo, 32-bit float, 48kHz) + _asio = New BassAsioHandler(True, 0, 0, 2, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT, 48000) + ' set the full-duplex option to the first ASIO output device and channel + ' the ASIO output format will aways be the same as the input for full-duplex + _asio.SetFullDuplex(0, 0) ' first output device and channel + ' start ASIO + _asio.Start(0) + ... + ' remove the full-duplex option and leave the channel enabled + _asio.RemoveFullDuplex(False) + ' but pause the unused output channel + BassAsio.BASS_ASIO_ChannelPause(False, 0) + ... + + + + + + Mirrors the current ASIO to the given output channel. + + The output channel number... 0 = first. + On success is returned, else will be returned (use to retrieve the error code). + + This function allows the input or output to be duplicated in other output channel. Mirroring is only available on the same ASIO ! + If you need to monitor an input channel on a different ASIO device, you might use the method instead. + The following will be done internally: + 1. The ASIO will only be stopped, if already started - it will automatically be started again if needed. + 2. The ASIO output will be enabled and mirrored (only if not already enabled). All according to the given , meaning starting with the this one and the next channels will be used as the mirror channels. + To disable and remove the mirror option call . + + + Automatic use of the BassAsioHandler (recording input, mirrored): + + private BassAsioHandler _asio; + ... + // assign ASIO input to the first device and channel (stereo, 32-bit float, 48kHz) + _asio = new BassAsioHandler(true, 0, 0, 2, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT, 48000); + // set the mirror option to the first ASIO output device and channel + _asio.SetMirror(0); + ... + // start ASIO + _asio.Start(0); + ... + // remove the mirror when not needed + _asio.RemoveMirror(); + ... + + + Private _asio As BassAsioHandler + ... + ' assign ASIO input to the first device and channel (stereo, 32-bit float, 48kHz) + _asio = New BassAsioHandler(True, 0, 0, 2, BASSASIOFormat.BASS_ASIO_FORMAT_FLOAT, 48000) + ' set the mirror option to the first ASIO output device and channel + _asio.SetMirror(0) + ... + ' start ASIO + _asio.Start(0) + ... + ' remove the mirror when not needed + _asio.RemoveMirror() + ... + + + + + + Removes a mirror set on the current ASIO . + + On success is returned, else will be returned (use to retrieve the error code). + The mirror option must have been set before via . + The following will be done internally: + 1. The ASIO will be stopped (if already started). + 2. The ASIO output will be disabled. + 3. The ASIO device will be started again (only, if it has been started before). + CAUTION: This method will always disable the (s)! + + + + + Provides a ready made callback procedure which might be used for ASIO output. + + Dealing with an input channel? Must be , since we are dealing with Asio output. + The output channel number... 0 = first. + The pointer to the buffer in which to put the data to output. + The number of BYTES to process. + Not used. + The number of bytes written. + Notes: + In order to use this default output ASIO callback (playback), you need to make sure that you use this callback only with ASIO output ( must be ). + Furthermore the following should be considered: If the underlying stream channel is at the end (all data was decoded), + this callback does NOT automatically pause ASIO via or . + So you need to do that by yourself (if you whish to save some performance), e.g. setup a BASS_SYNC_END on the . + If the underlying returns less data, than requested the ASIO output buffer will be filled with 0's (silence). + Internally will be called on the underlying to request sample data, before the sample data is send to the ASIO output. + If you intend to overload this callback in a derive implementation make sure to call the base method to not loose any functionatily. + + + Implementing your own callback in a derived implementation: + + public class MyAsioHandler : BassAsioHandler + { + + public override int AsioOutputCallback(bool input, int channel, IntPtr buffer, int length, IntPtr user) + { + // buffer is not filled + // do your own stuff here... + int len = base.AsioOutputCallback(input, channel, buffer, length, user); + if (len > 0) + { + // buffer is already filled + // do your own stuff here... + } + return len; + } + + } + + + Public Class MyAsioHandler + Inherits BassAsioHandler + + Public Overrides Function AsioOutputCallback(input As Boolean, channel As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Integer + ' buffer is already filled + ' do your own stuff here... + Dim len As Integer = MyBase.AsioOutputCallback(input, channel, buffer, length, user) + If len > 0 Then + ' buffer is already filled + ' do your own stuff here... + End If + Return len + End Function + + End Class + + + + + + Provides a ready made callback procedure which might be used for ASIO input. + + Dealing with an input channel? Must be , since we are only dealing with Asio input. + The input channel number... 0 = first. + The pointer to the buffer containing the recorded data (input channel). + The number of BYTES to process. + Not used. + Returns 0, since we are only dealing with Asio input. + + To receive the recorded sample data you might use the and set up a DSP on it. + If you intend to overload this callback in a derive implementation make sure to call the base method to not loose any functionatily. + + + Implementing your own callback in a derived implementation: + + public class MyAsioHandler : BassAsioHandler + { + + public override int AsioInputCallback(bool input, int channel, IntPtr buffer, int length, IntPtr user) + { + // InputChannel not applied yet + // do your own stuff here... + int len = base.AsioInputCallback(input, channel, buffer, length, user); + // InputChannel already applied + // do your own stuff here... + return len; + } + + } + + + Public Class MyAsioHandler + Inherits BassAsioHandler + + Public Overrides Function AsioInputCallback(input As Boolean, channel As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Integer + ' InputChannel not applied yet + ' do your own stuff here... + Dim len As Integer = MyBase.AsioInputCallback(input, channel, buffer, length, user) + ' InputChannel already applied + ' do your own stuff here... + Return len + End Function + + End Class + + + + + + Provides a ready made callback procedure which might be used for full-duplex ASIO input to Asio output. + + Dealing with an input channel? = an output channel, = an input channel (both input and output must be supported by this callback). + The input/output channel number... 0 = first. + The pointer to the buffer containing the recorded data (if input), or in which to put the data to output (if output). + The number of BYTES to process. + Not used. + The number of bytes written (if output), else 0 (if input). + + To apply DSP/FX independetly to the input and output you might use the and respectively. + If you intend to overload this callback in a derive implementation make sure to call the base method to not loose any functionatily. + + + Implementing your own callback in a derived implementation: + + public class MyAsioHandler : BassAsioHandler + { + + public override int AsioToAsioFullDuplexCallback(bool input, int channel, IntPtr buffer, int length, IntPtr user) + { + // FullDuplex not applied yet + if (input) + { + // do your own input stuff here... + } + else + { + // do your own output stuff here... + } + int len = base.AsioToAsioFullDuplexCallback(input, channel, buffer, length, user); + // FullDuplex already applied + if (input) + { + // do your own input stuff here... + } + else + { + // do your own output stuff here... + } + return len; + } + + } + + + Public Class MyAsioHandler + Inherits BassAsioHandler + + Public Overrides Function AsioToAsioFullDuplexCallback(input As Boolean, channel As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Integer + ' FullDuplex not applied yet + If input Then + ' do your own input stuff here... + Else + ' do your own output stuff here... + End If + Dim len As Integer = MyBase.AsioToAsioFullDuplexCallback(input, channel, buffer, length, user) + ' FullDuplex already applied + If input Then + ' do your own input stuff here... + Else + ' do your own output stuff here... + End If + Return len + End Function + + End Class + + + + + + Provides a ready made callback procedure which might be used for full-duplex ASIO input to Bass output. + + Dealing with an input channel? Must be , since we are only dealing with Asio input (full-duplex output is via ). + The input channel number... 0 = first. + The pointer to the buffer containing the recorded data. + The number of BYTES to process. + Not used. + Returns 0, since we are only dealing with Asio input. + + To apply DSP/FX independetly to the input and output you might use the and respectively. + If you intend to overload this callback in a derive implementation make sure to call the base method to not loose any functionatily. + + + Implementing your own callback in a derived implementation: + + public class MyAsioHandler : BassAsioHandler + { + + public override int AsioToBassFullDuplexCallback(bool input, int channel, IntPtr buffer, int length, IntPtr user) + { + // FullDuplex not applied yet + if (input) + { + // do your own input stuff here... + } + else + { + // do your own output stuff here... + } + int len = base.AsioToBassFullDuplexCallback(input, channel, buffer, length, user); + // FullDuplex already applied + if (input) + { + // do your own input stuff here... + } + else + { + // do your own output stuff here... + } + return len; + } + + } + + + Public Class MyAsioHandler + Inherits BassAsioHandler + + Public Overrides Function AsioToBassFullDuplexCallback(input As Boolean, channel As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Integer + ' FullDuplex not applied yet + If input Then + ' do your own input stuff here... + Else + ' do your own output stuff here... + End If + Dim len As Integer = MyBase.AsioToBassFullDuplexCallback(input, channel, buffer, length, user) + ' FullDuplex already applied + If input Then + ' do your own input stuff here... + Else + ' do your own output stuff here... + End If + Return len + End Function + + End Class + + + + + + Gets or Sets the master volume of the between 0 (silent) and 1 (full). + + Whereas the and the properties directly effect the internally used channel volume, + this property effects the global ASIO device volume setting. + The volume level ranges from 0 (silent) to 1 (maximum). + + + + + Gets the currently being used by the Asio handler. + + + + + Gets or Sets the volume of the (and all joined ) between 0 (silent) and 1 (full). + + Setting the volume uses the property in case of multi-channel ASIO ( is greater than 1). + The volume level ranges from 0 (silent) to 1 (normal) or above 1 to amplify the sound. + + + + + Gets or Sets the volume of the (and all attached ) between 0 (silent) and 1 (full). + + Setting the volume uses the property in case of multi-channel ASIO ( is greater than 1). + The volume level ranges from 0 (silent) to 1 (normal) or above 1 to amplify the sound. + + + + + Gets or Sets the panning of the (and all joined ) between -1 (left) to +1 (right), 0=centered. + + Setting the panning uses the property in order to calculate the individual channel volume. + E.g. if you set the panning to -0.7 at a volume of 1.0: chan1-volume (left) = 0.3, chan2-volume (right) = 1.0. + The panning value ranges from -1 (left) to 0 (center) to +1 (right). + In case of multi-channel (not stereo, is greater than 2) the left/right positions are interleaved between the additional channels. + + + + + Gets or Sets the panning of the (and all attached ) between -1 (left) to +1 (right), 0=centered. + + Setting the panning uses the property in order to calculate the individual channel volume. + E.g. if you set the panning to -0.7 at a volume of 1.0: chan1-volume (left) = 0.3, chan2-volume (right) = 1.0. + The panning value ranges from -1.0 (left) to 0.0 (center) to +1.0 (right). + In case of multi-channel (not stereo, is greater than 2) the left/right positions are interleaved between the additional channels. + + + + + Returns , if the ASIO handler is used with an ASIO input device. + + + + + Returns the ASIO device being used by the Asio handler. + + + + + Returns the first ASIO channel being used. + + The class will automatically join ASIO channels together when needed (done in the constructor). + This property reflects the first ASIO channel being used. The property will tell you how many channels are effectively joined and enabled starting with this channel. + You can not change the number of ASIO channels once joined and enabled. + Caution: Once you created an instance of this class, the respective ASIO channels are joined and enabled. + Disposing an instance of this class will not automatically unjoin and disable the used ASIO channels. + If you want to do so, please call the appropriate overload of the method manually. + + + + + Returns , if the ASIO handler is used with an ASIO input device and the full-duplex option was set via . + + + + + Returns the full-duplex ASIO output device being used (or -1, if not used). + + Note: This property might also return the full-duplex BASS device, if the related overload was used. + + + + Returns the first full-duplex ASIO output channel being used (or -1, if not used). + + Note: This property might also return -1 if the full-duplex option was used with a BASS device, if the related overload was used. + If the ASIO is a multi-channel (the property is greater than 1) this property will return the first full-duplex channel only. + However, full-duplex always enables channels, starting with this one. + + + + + Gets or Sets the bypass flag for full-duplex ASIO output processing (default is ). + + If this property is set to any full-duplex output processing is bypassed. + When setting this property to prior to creating a full-duplex via the method this enables you to start full-duplex without processing the output yet. + Setting this property to will start the full-duplex output processing. + This flag will automatically set back to when calling . + + + + + Returns if the ASIO is being mirrored to another output channel. + + You can enable mirroring with the method and remove it with the method. + Mirroring allows an ASIO input or output to be duplicated in other output channel (the ). + + + + + Gets the first ASIO mirror channel (or -1 if not mirrored). + + You can enable mirroring with the method and remove it with the method. + Mirroring allows an ASIO input or output to be duplicated in other output channel. The property returnes the mirror channel. + If the ASIO is a multi-channel (the property is greater than 1) this property will return the first mirrored channel only. + However, mirroring will always mirror channels, starting with this one. + + + + + Gets or Sets the actual ASIO channel sample rate in Hz (default is 48000). + + By default the samplerate will automatically be adjusted according to the being used. + However, you might change the samplerate for this ASIO manually, which might result in resampling, since this property does not change the ASIO device samplerate. + + + + Gets the total number of ASIO channel which are joined together, starting with . + + The class will automatically join ASIO channels together when needed (done in the constructor). + This property reflects the total of ASIO channels used. Depending on which constructor overload you used, this number can be based on the number of channels of the given . + You can not change the number of ASIO channels once joined and enabled. + Caution: Once you created an instance of this class, the respective ASIO channels are joined and enabled. + Disposing an instance of this class will not automatically unjoin and disable the used ASIO channels. + If you want to do so, please call the appropriate overload of the method manually. + + + + + Gets or Sets the actual ASIO channel format (default is BASS_ASIO_FORMAT_FLOAT). + + By default the format will automatically be adjusted according to the being used. + However, you might change the format for this ASIO manually. + + + + Gets or Sets the BASS output channel handle which is used with this ASIO handler. + + + When using the ASIO handler with an ASIO input device this channel is not available (unless you use the method, + in which case you might use this property to access the full-duplex output channel to apply DSP/FX). + When using the ASIO handler with an ASIO output device this channel will be assigned once and can later be changed by calling + and will represent the channel feeding the ASIO output with sample data. Tyically a decoding channel must be used, + but a recording channel will also work, since the interal ASIO procedure being used simply calls to pull the sample data from it as needed and reqested by ASIO. + Caution: Setting this parameter manually might break the ASIO chain - only assign it manually, if the BASS chanel uses the same format and samplerate as the related ASIO channel. + + + + + Returns , if resampling takes place on the used and . + + Resampling is needed, if the ASIO channel samplerate is different than the ASIO device samplerate. + If you are using ASIO input with the full-duplex option this property will check both, if resampling happens either on the ASIO input or on the ASIO output. + + + + Returns an input channel which allows you to retrieve the recorded sample data and/or apply any DSP/FX on Asio input. + + When you are using ASIO with input ( must return ) and have set the property to + you might use this channel to setup any DSP/FX to be applied to the Asio input or just retrieve the recorded sample data. + Any DSP/FX set on this channel will also be passed through to the output, if you are using . + As the InputChannel is a dummy custom decoding stream you can not call directly on it in order to directly get the sample data; + nor can you use it directly as a source stream for any (mixer)output! + Instead use a via to retrieve the sample data. + Note: However, you might independently set any DSP/FX on the full-duplex output using the instead. + + + + + Enables the use of the channel with ASIO input (which is the default for Asio input). + + When you are using ASIO with input ( must return ) and set this property to + you might use the to setup any DSP/FX to be applied to the Asio input or retrieve the recorded sample data. + Any DSP/FX set on this channel will also be passed through to the output, if you are using . + Note: However, you might independently set any DSP/FX on the full-duplex output using the instead. + + + + + Event handler used to notify that an asio handler notification event (sync) has occurred. + + + The contains a which allows you to react to a possible sync scenarios. + + + + + Definition of the event handler. + + + This definition complies with the .NET Framework's standard for event handlers. + The sender is always set to the object instance that raised the event. + + + + + EventArgs class to be passed as the second parameter of a event handler. + + + This class provides all the information relevant to an event which might occur to a class. + + + + + Initializes a new instance of the BassAsioHandlerEventArgs class by initializing all of its properties. + + The type of event which occurred (see ). + Some data which should be passed along with the notification event. + + + + Gets the type of sync which occurred. + + + + + Gets the data which was passed along with the event. + + + + + Types of event that has occurred with the class. + + + A variable of this type is passed inside the object + for the event. + + + + + The Asio source is stalled. + data: the source stream channel which was stalled. + + + + + The Asio source is resumed. + data: the source stream channel which was resumed. + + + + + BASS.NET API wrapper for BASS_FX.DLL + Requires: bass_fx.dll - DSP and Effect support Add-On - available @ www.un4seen.com. + + + BASS_FX is an extension to the BASS audio library, providing a complete set of DSP functions to start programming your own DJ software. + Programmed to enable the simple and even the advanced programmers/users to have in their programs some sound effects without knowing any DSP at all. + + + + + Current BASS_FX version (without minor revision). + + + + + NOT used - all members are static! + + + + + Retrieves the version number of the BASS_FX.DLL that is loaded. + + The BASS_FX version. For example, 0x02040103 (hex), would be version 2.4.1.3. + There is no guarantee that a previous or future version of BASS_FX supports all the BASS_FX functions that you are using, so you should always use this function to make sure the correct version is loaded. + It is safe to assume that future minor revisions (indicated in the LOWORD) will be fully compatible. + You might use the global constant to check the major revision. + Note: Calling this method will also automatically load the library into memory. + + + Checking the major version only: + + if ( Utils.HighWord(BassFx.BASS_FX_GetVersion()) != BassFx.BASSFXVERSION ) + { + MessageBox.Show(this, "Wrong BassFx Version!"); + } + + + If Utils.HighWord(BassFx.BASS_FX_GetVersion()) <> BassFx.BASSFXVERSION Then + MessageBox.Show(Me, "Wrong BassFx Version!") + End If + + Checking for full version "2.4.1.3": + + if (BassFx.BASS_FX_GetVersion() < Utils.MakeLong(0x0103, 0x0204)) + { + MessageBox.Show(this, "Wrong BassFx Version!"); + } + + + If BassFx.BASS_FX_GetVersion() < Utils.MakeLong(&H103, &H204) Then + MessageBox.Show(Me, "Wrong BassFx Version!") + End If + + + + + + Retrieves the version of the BASS_FX.DLL that is loaded. + + The number of components to use. The fieldCount ranges from 1 to 4 (major.minor.build.revision). + The BASS_FX version (major.minor.build.revision). + There is no guarantee that a previous or future version of BASS_FX supports all the BASS_FX functions that you are using, so you should always use this function to make sure the correct version is loaded. + It is safe to assume that future minor revisions (indicated in the LOWORD) will be fully compatible. + Note: Calling this method will also automatically load the library into memory. + + + + Version expectedVersion = new Version(2, 4); + if (BassFx.BASS_FX_GetVersion(2) < expectedVersion) + { + MessageBox.Show( this, "Wrong BassFx Version!" ); + } + + + Dim expectedVersion As New Version(2, 4) + If BassFx.BASS_FX_GetVersion(2) < expectedVersion Then + MessageBox.Show(Me, "Wrong BassFx Version!") + End If + + + + + + Creates a resampling stream from a decoding channel. + + Stream/music/wma/cd/any other supported add-on format using a decoding channel (use BASS_STREAM_DECODE when creating the channel). + A combination of the following flags (see ): + + BASS_SAMPLE_LOOPLooped? Note that only complete sample loops are allowed by DirectSound (ie. you can't loop just part of a sample). + BASS_SAMPLE_SOFTWAREForce the sample to not use hardware mixing. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D samples must be mono (use BASS_SAMPLE_MONO). + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_AUTOFREEAutomatically free the stream's resources when it has reached the end, or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + BASS_FX_FREESOURCEFree the source handle as well when the tempo channel is freed. + + + If successful, the tempo stream handle is returned, else 0 is returned. Use to get the error code. + + Multi-channels are supported. + Use / to get or set the attributes of a tempo stream: + + BASS_ATTRIB_TEMPOThe tempo of a channel in percent [-95%...0...+5000%]. + BASS_ATTRIB_TEMPO_PITCHThe pitch of a channel in semitones [-60...0...+60]. + BASS_ATTRIB_TEMPO_FREQThe sample rate of a channel in Hz (but calculates by the same % as BASS_ATTRIB_TEMPO). + + These attributes can either be applied to the tempo channel or the underlying decoding source channel. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_FX_ERROR_NODECODEThe is not a decoding channel. Make sure the channel was created using the BASS_STREAM_DECODE or BASS_MUSIC_DECODE flag. + BASS_ERROR_FORMATThe 's format is not supported. Make sure the channel is either Stereo or Mono. + + + Tuning the option attributes parameters (see ): + The time-stretch algorithm has few parameters that can be tuned to optimize sound quality for certain application. The current default parameters have been chosen by iterative if-then analysis (read: "trial and error") to obtain best subjective sound quality in pop/rock music processing, but in applications processing different kind of sound the default parameter set may result into a sub-optimal result. + + + BASS_ATTRIB_TEMPO_OPTION_USE_AA_FILTER (default = ): + Use FIR low-pass (anti-alias) filter (gain speed, lose quality)? : =1 / =0. + + + + BASS_ATTRIB_TEMPO_OPTION_AA_FILTER_LENGTH (default = 32): + The FIR low-pass (anti-alias) filter length in taps: between 8 and 128 (should be around %4). + + + + BASS_ATTRIB_TEMPO_OPTION_USE_QUICKALGO (default = ): + Use quicker tempo change algorithm (gain speed, lose quality)? =1 / =0. + + + + BASS_ATTRIB_TEMPO_OPTION_SEQUENCE_MS (default = 82): + This is the default length of a single processing sequence in milliseconds which determines the how the original sound is chopped in the time-stretch algorithm. Larger values mean fewer sequences are used in processing. In principle a larger value sounds better when slowing down the tempo, but worse when increasing the tempo and vice versa. + + + + BASS_ATTRIB_TEMPO_OPTION_SEEKWINDOW_MS (default = 14): + The seeking window default length in milliseconds is for the algorithm that seeks the best possible overlapping location. This determines from how wide a sample "window" the algorithm can use to find an optimal mixing location when the sound sequences are to be linked back together. + The bigger this window setting is, the higher the possibility to find a better mixing position becomes, but at the same time large values may cause a "drifting" sound artifact because neighboring sequences can be chosen at more uneven intervals. If there's a disturbing artifact that sounds as if a constant frequency was drifting around, try reducing this setting. + + + + BASS_ATTRIB_TEMPO_OPTION_OVERLAP_MS (default = 12): + Overlap length in milliseconds. When the sound sequences are mixed back together to form again a continuous sound stream, this parameter defines how much the ends of the consecutive sequences will overlap with each other. + This shouldn't be that critical parameter. If you reduce the BASS_FX_TEMPO_OPTION_SEQUENCE_MS setting by a large amount, you might wish to try a smaller value on this + + + + BASS_ATTRIB_TEMPO_OPTION_PREVENT_CLICK (bool, default = FALSE): + Prevents clicks when changing the tempo from or over the zero position. + Note: This involves a slight sound quality compromise by disallowing swapping processing stage order and affecting situations that pitch is decreased from the nominal. + + + + The table below summarizes how the parameters can be adjusted for different applications: + + Parameter:Effect: + SEQUENCE_MS + + Default value magnitude: Default value is relatively large, chosen for slowing down music tempo. + Larger value affects: Larger value is usually better for slowing down tempo. Growing the value decelerates the "echoing" artifact when slowing down the tempo. + Smaller value affects: Smaller value might be better for speeding up tempo. Reducing the value accelerates the "echoing" artifact when slowing down the tempo. + Music: Default value usually good. + Speech: A smaller value than default might be better. + Effect in CPU burden: Increasing the parameter value reduces computation burden. + + + SEEKWINDOW_MS + + Default value magnitude: Default value is relatively large, chosen for slowing down music tempo. + Larger value affects: Larger value eases finding a good mixing position, but may cause a "drifting" artifact. + Smaller value affects: Smaller reduce possibility to find a good mixing position, but reduce the "drifting" artifact. + Music: Default value usually good, unless a "drifting" artifact is disturbing. + Speech: Default value usually good. + Effect in CPU burden: Increasing the parameter value increases computation burden. + + + OVERLAP_MS + + Default value magnitude: Default value is relatively large, chosen to suit with above parameters. + Larger value affects: -- + Smaller value affects: If you reduce the "sequence ms" setting, you might wish to try a smaller value. + Music: -- + Speech: -- + Effect in CPU burden: Increasing the parameter value increases computation burden. + + + + Performance Optimizations: + + + The time-stretch routine has a 'quick' mode that substantially speeds up the algorithm but may degrade the sound quality by a small amount. This mode is activated by BASS_ATTRIB_TEMPO_OPTION_USE_QUICKALGO and value =1. + + + Intel SSE optimized routines are used with compatible CPUs when floating point sample type is used. SSE optimizations are currently implemented for Win32 platform only. Processors compatible with SSE extension are Intel processors starting from Pentium-III, and AMD processors starting from Athlon XP. + + + AMD 3DNow! optimized routines are used with compatible CPUs when floating point sample type is used, but SSE extension isn't supported . 3DNow! optimizations are currently implemented for Win32 platform only. These optimizations are used in AMD K6-2 and Athlon (classic) CPU's; better performing SSE routines are used with AMD processor starting from Athlon XP. + + + + + Create a playing tempo stream out of a decoding stream and loop it: + + // the source channel + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_STREAM_DECODE); + // the tempo channel + int streamFX = BassFx.BASS_FX_TempoCreate(stream, BASSFlag.BASS_FX_FREESOURCE); + ... + // change the sampling rate by 20%, the streamFX will be played faster + Bass.BASS_ChannelSetAttribute(streamFX, BASSAttribute.BASS_ATTRIB_TEMPO_FREQ, 0.2f); + + // change the tempo by -15%, the streamFX will be slower + Bass.BASS_ChannelSetAttribute(streamFX, BASSAttribute.BASS_ATTRIB_TEMPO, -0.15f); + + // change the pitch (key) by one octave (12 semitones) + Bass.BASS_ChannelSetAttribute(streamFX, BASSAttribute.BASS_ATTRIB_TEMPO, 12f); + + + ' the source channel + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_STREAM_DECODE) + ' the tempo channel + Dim streamFX As Integer = BassFx.BASS_FX_TempoCreate(stream, BASSFlag.BASS_FX_FREESOURCE) + ... + ' change the sampling rate by 20%, the streamFX will be played faster + Bass.BASS_ChannelSetAttribute(streamFX, BASSAttribute.BASS_ATTRIB_TEMPO_FREQ, 0.2F) + + ' change the tempo by -15%, the streamFX will be slower + Bass.BASS_ChannelSetAttribute(streamFX, BASSAttribute.BASS_ATTRIB_TEMPO, -0.15F) + + ' change the pitch (key) by one octave (12 semitones) + Bass.BASS_ChannelSetAttribute(streamFX, BASSAttribute.BASS_ATTRIB_TEMPO, 12F) + + + + + + Get the source channel handle. + + Tempo stream handle. + If successful, the source channel handle is returned, else 0 is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + // the source channel + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_STREAM_DECODE); + // the tempo channel + int streamFX = BassFx.BASS_FX_TempoCreate(stream, BASSFlag.BASS_FX_FREESOURCE); + ... + // this will return 'stream' + int chan = BassFx.BASS_FX_TempoGetSource(streamFX); + + + ' the source channel + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_STREAM_DECODE) + ' the tempo channel + Dim streamFX As Integer = BassFx.BASS_FX_TempoCreate(stream, BASSFlag.BASS_FX_FREESOURCE) + ... + ' this will return 'stream' + Dim chan As Integer = BassFx.BASS_FX_TempoGetSource(streamFX); + + + + + + Get the ratio of the resulting rate and source rate (the resampling ratio). + + Tempo stream (or source channel) handle. + If successful, the resampling ratio is returned, else 0 is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + Will return eg. 1.2 if the samplerate was increased by 20%: + + float ratio = BassFx.BASS_FX_TempoGetRateRatio(streamFX); + + + Dim ratio As Single = BassFx.BASS_FX_TempoGetRateRatio(streamFX) + + + + + + Creates a reversed stream from a decoding channel. + + Stream/music/wma/cd/any other supported add-on format using a decoding channel. + Length of decoding blocks in seconds. Larger blocks means less seeking overhead but larger spikes. + A combination of the following flags (see ): + + BASS_SAMPLE_LOOPLooped? Note that only complete sample loops are allowed by DirectSound (ie. you can't loop just part of a sample). + BASS_SAMPLE_SOFTWAREForce the sample to not use hardware mixing. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D samples must be mono (use BASS_SAMPLE_MONO). + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_AUTOFREEAutomatically free the stream's resources when it has reached the end, or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + BASS_FX_FREESOURCEFree the source handle as well when the reverse channel is freed. + + + If successful, the handle of the reversed stream is returned, else 0 is returned. Use to get the error code. + MODs are supported, if BASS_MUSIC_PRESCAN flag was applied to a source handle. Enable reverse supported flags in and the others to source handle. + For better MP3/2/1 reverse playback create the source stream using the BASS_STREAM_PRESCAN flag. + Use / to get or set the attributes of a reverse stream: + + BASS_ATTRIB_REVERSE_DIRThe playback direction of a reverse channel (-1(less than 0)=reverse, 1(greater or equal 0)=forward, or use one of the flags). + + These attributes can either be applied to the reverse channel or the underlying decoding source channel. + Note, that when playing the channel reverse, the end of a reverse stream is reached at the logial beginning of the stream (this also applies to BASS_SYNC_END). + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_FX_ERROR_NODECODEThe is not a decoding channel. Make sure the channel was created using the BASS_STREAM_DECODE or BASS_MUSIC_DECODE flag. + BASS_ERROR_HANDLE is not valid. + + + + + Create a reverse stream with 2 seconds decoding blocks: + + // the source channel + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_STREAM_DECODE | + BASSFlag.BASS_STREAM_PRESCAN); + // the reverse channel + int streamFX = BassFx.BASS_FX_ReverseCreate(stream, 2f, BASSFlag.BASS_FX_FREESOURCE); + ... + // play the channel reverse + Bass.BASS_ChannelSetAttribute(streamFX, BASSAttribute.BASS_ATTRIB_REVERSE_DIR, -1f); + // or + Bass.BASS_ChannelSetAttribute(streamFX, BASSAttribute.BASS_ATTRIB_REVERSE_DIR, (float)BASSFXReverse.BASS_FX_RVS_REVERSE); + + // play the channel forward + Bass.BASS_ChannelSetAttribute(streamFX, BASSAttribute.BASS_ATTRIB_REVERSE_DIR, 1f); + // or + Bass.BASS_ChannelSetAttribute(streamFX, BASSAttribute.BASS_ATTRIB_REVERSE_DIR, (float)BASSFXReverse.BASS_FX_RVS_FORWARD); + + + ' the source channel + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_STREAM_DECODE Or + BASSFlag.BASS_STREAM_PRESCAN) + ' the tempo channel + Dim streamFX As Integer = BassFx.BASS_FX_ReverseCreate(stream, 2F, BASSFlag.BASS_FX_FREESOURCE) + ... + ' play the channel reverse + Bass.BASS_ChannelSetAttribute(streamFX, BASSAttribute.BASS_ATTRIB_REVERSE_DIR, -1F) + ' or + Bass.BASS_ChannelSetAttribute(streamFX, BASSAttribute.BASS_ATTRIB_REVERSE_DIR, CSng(BASSFXReverse.BASS_FX_RVS_REVERSE)) + + ' play the channel forward + Bass.BASS_ChannelSetAttribute(streamFX, BASSAttribute.BASS_ATTRIB_REVERSE_DIR, 1F) + ' or + Bass.BASS_ChannelSetAttribute(streamFX, BASSAttribute.BASS_ATTRIB_REVERSE_DIR, CSng(BASSFXReverse.BASS_FX_RVS_FORWARD)) + + + + + + Get the source channel handle of the reversed stream. + + The handle of the reversed stream. + If successful, the handle of the source of the reversed stream is returned, else 0 is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + // the source channel + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_STREAM_DECODE | + BASSFlag.BASS_STREAM_PRESCAN); + // the reverse channel + int streamFX = BassFx.BASS_FX_ReverseCreate(stream, 2f, BASSFlag.BASS_FX_FREESOURCE); + ... + // this will return 'stream' + int chan = BassFx.BASS_FX_ReverseGetSource(streamFX); + + + ' the source channel + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_STREAM_DECODE Or + BASSFlag.BASS_STREAM_PRESCAN) + ' the tempo channel + Dim streamFX As Integer = BassFx.BASS_FX_ReverseCreate(stream, 2F, BASSFlag.BASS_FX_FREESOURCE) + ... + ' this will return 'stream' + Dim chan As Integer = BassFx.BASS_FX_ReverseGetSource(streamFX); + + + + + + Get the original BPM of a decoding channel. + + Stream/music/wma/cd/any other supported add-on format using a decoding channel. + Start detecting position in seconds. + End detecting position in seconds (> 0). + Set min & max bpm, e.g: (LowWord, HighWord), LowWord=Min, HighWord=Max. 0 = defaults to 45/230. + Use one of the following (see ): + + BASS_FX_BPM_BKGRNDIf in use, then you can do other stuff while detection's in process. + BASS_FX_BPM_MULT2If in use, then the detected BPM will be automatically multiplied by 2 if (BPM < minBPM*2) - recommended setting. + BASS_FX_FREESOURCEFree the source handle as well? + + + User defined function to receive the process in percents (see ), use if not in use. + If successful, the original BPM value is returned, else -1 is returned. Use to get the error code. + + The BPM detection algorithm works by detecting repeating low-frequency (<250Hz) sound patterns and thus works mostly with most rock/pop music with bass or drum beat. + The BPM detection doesn't work on pieces such as classical music without distinct, repeating bass frequency patterns. Also pieces with varying tempo, varying bass patterns or very complex bass patterns (jazz, hiphop) may produce odd BPM readings. + In cases when the bass pattern drifts a bit around a nominal beat rate (e.g. drummer is again drunken ;-), the BPM algorithm may report incorrect harmonic one-halft to one-thirdth of the correct BPM value. + In such case the system could for example report BPM value of 50 or 100 instead of correct BPM value of 150. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_FX_ERROR_NODECODEThe is not a decoding channel. Make sure the channel was created using the BASS_STREAM_DECODE or BASS_MUSIC_DECODE flag. + BASS_ERROR_FORMATThe 's format is not supported. Make sure the channel is either Stereo or Mono. + BASS_ERROR_ILLPARAMAn illegal parameter was specified. + BASS_FX_ERROR_BPMINUSEBPM detection, for this is already in use. + + + + + Get the BPM value for the first 120 seconds of a track: + + private BPMPROCESSPROC _bpmProc; + ... + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_STREAM_DECODE); + _bpmProc = new BPMPROCESSPROC(MyBPMProc); + float bpm = BassFx.BASS_FX_BPM_DecodeGet(stream, 0.0, 120.0, 0, BASSFXBpm.BASS_FX_BPM_BKGRND | + BASSFXBpm.BASS_FX_FREESOURCE | + BASSFXBpm.BASS_FX_BPM_MULT2, _bpmProc); + BassFx.BASS_FX_BPM_Free(stream); + ... + private void MyBPMProc(int channel, float percent) + { + Console.Write("{0}%\r", percent); + } + + + Private _bpmProc As BPMPROCESSPROC + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_STREAM_DECODE) + _bpmProc = New BPMPROCESSPROC(AddressOf MyBPMProc) + Dim bpm As Single = BassFx.BASS_FX_BPM_DecodeGet(stream, 0.0, 120.0, 0, BASSFXBpm.BASS_FX_BPM_BKGRND Or + BASSFXBpm.BASS_FX_FREESOURCE Or + BASSFXBpm.BASS_FX_BPM_MULT2, _bpmProc) + BassFx.BASS_FX_BPM_Free(stream) + ... + Private Sub MyBPMProc(channel As Integer, percent As Single) + Console.Write("{0}%\r", percent) + End Sub + + + + + + Enable getting Beat position in seconds of the decoded channel using a callback function. + + Stream/music/wma/cd/any other supported add-on format using a decoding channel. + Start detecting position in seconds. + End detecting position in seconds (> 0). + Use one of the following (see ): + + BASS_FX_BPM_BKGRNDIf in use, then you can do other stuff while detection's in process. + BASS_FX_FREESOURCEFree the source handle as well? + + + User defined function to receive the beat position values (see ). + User instance data to pass to the callback function. + If successful, is returned, else is returned. Use to get the error code. + This method works pretty much the same as respectivly - it is almost a mix of the two of them. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_FX_ERROR_NODECODEThe is not a decoding channel. Make sure the channel was created using the BASS_STREAM_DECODE or BASS_MUSIC_DECODE flag. + BASS_ERROR_ILLPARAMAn illegal parameter was specified. + BASS_FX_ERROR_BPMINUSEBeat detection, for this is already in use. + + + + + Get all the beat positions of the first minute of a track: + + private BPMBEATPROC _beatProc; + ... + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_STREAM_DECODE); + _beatProc = new BPMBEATPROC(MyBeatProc); + BassFx.BASS_FX_BPM_BeatDecodeGet(stream, 0.0, 60.0, BASSFXBpm.BASS_FX_BPM_BKGRND, _beatProc, IntPtr.Zero); + BassFx.BASS_FX_BPM_BeatFree(stream); + ... + private void MyBeatProc(int channel, double beatpos, IntPtr user) + { + Console.WriteLine("Beat at: {0}", beatpos); + } + + + Private _beatProc As BPMBEATPROC + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_STREAM_DECODE) + _beatProc = New BPMBEATPROC(AddressOf MyBeatProc) + BassFx.BASS_FX_BPM_BeatDecodeGet(stream, 0.0, 60.0, BASSFXBpm.BASS_FX_BPM_BKGRND, _beatProc, IntPtr.Zero) + BassFx.BASS_FX_BPM_BeatFree(stream) + ... + Private Sub MyBeatProc(channel As Integer, beatpos As Double, user As IntPtr) + Console.WriteLine("Beat at: {0}", beatpos) + End Sub + + + + + + Translate the given BPM to FREQ/PERCENT and vice versa or multiply BPM by 2. + + Stream/music/wma/cd/any other supported add-on format. + Specify a value to translate to a given option (no matter if used X2). + Any of the following translation options (see ): + + BASS_FX_BPM_TRAN_X2Multiply the original BPM value by 2. This may be used only once, and will change the original BPM as well. + BASS_FX_BPM_TRAN_2FREQBPM value to Frequency. + BASS_FX_BPM_TRAN_FREQ2Frequency to BPM value. + BASS_FX_BPM_TRAN_2PERCENTPercents to BPM value. + BASS_FX_BPM_TRAN_PERCENT2BPM value to Percents. + + + If successful, the newly calculated value is returned, else -1 is returned. Use to get the error code. + + This function will not detect the BPM, it will just translate the detected original BPM value of a given handle. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ILLPARAMAn illegal parameter was specified. + BASS_ERROR_ALREADYBASS_FX_BPM_TRAN_X2 already used on this handle. + + + + + The following method does a simple translation assuming you have calculated the original BPM on a source channel: + + private float GetNewBPM(int sourceChannel, int tempoChannel) + { + return BassFx.BASS_FX_BPM_Translate(sourceChannel, + BassFx.BASS_FX_TempoGetRateRatio(tempoChannel) * 100f, + BASSFXBpmTrans.BASS_FX_BPM_PERCENT2); + } + + + Private Function GetNewBPM(sourceChannel As Integer, tempoChannel As Integer) As Single + Return BassFx.BASS_FX_BPM_Translate(sourceChannel, + BassFx.BASS_FX_TempoGetRateRatio(tempoChannel) * 100F, + BASSFXBpmTrans.BASS_FX_BPM_PERCENT2) + End Function + + + + + + Frees all resources used by a given handle. + + Stream/music/wma/cd/any other supported add-on format. + If successful, is returned, else is returned. Use to get the error code. + Used together with or . + If BASS_FX_FREESOURCE was used, this will also free the underlying decoding channel as well. + You can't set/get this flag with /. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + + Enable getting BPM value by period of time in seconds. + + Stream/music/wma/cd/any other supported add-on format. + User defined function to receive the bpm value (see ). + Detection period in seconds. + Set min & max bpm, e.g: (LowWord, HighWord), LowWord=Min, HighWord=Max. 0 = defaults to 45/230. + Use one of the following (see ): + + BASS_FX_BPM_MULT2If in use, then the detected BPM will be automatically multiplied by 2 if (BPM < minBPM*2) - recommended setting. + + + User instance data to pass to the callback function. + If successful, is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ILLPARAMAn illegal parameter was specified. + BASS_ERROR_ALREADYBASS_FX_BPM_TRAN_X2 already used on this handle. + + + + + Getting BPM values in periods of 10 seconds: + + private BPMPROC _bpmProc; + ... + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_STREAM_DECODE); + _bpmProc = new BPMPROC(MyBPMProc); + BassFx.BASS_FX_BPM_CallbackSet(stream, _bpmProc, 10.0, Utils.MakeLong(45,240), + BASSFXBpm.BASS_FX_BPM_MULT2, IntPtr.Zero); + ... + private void MyBPMProc(int handle, float bpm, IntPtr user) + { + Console.Write("BPM: {0}\r", bpm); + } + + + Private _bpmProc As BPMPROC + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_STREAM_DECODE) + _bpmProc = New BPMPROC(MyBPMProc) + BassFx.BASS_FX_BPM_CallbackSet(stream, _bpmProc, 10.0, Utils.MakeLong(45, 240), + BASSFXBpm.BASS_FX_BPM_MULT2, IntPtr.Zero) + ... + Private Sub MyBPMProc(handle As Integer, bpm As Single, user As IntPtr) + Console.Write("BPM: {0}" + ControlChars.Cr, bpm) + End Sub + + + + + + Reset the BPM buffers. + + Stream/music/wma/cd/any other supported add-on format. + If successful, is returned, else is returned. Use to get the error code. + + This function flushes the internal buffers of the BPM callback. The BPM callback is automatically reset by , except when called from a "mixtime" . + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + + Enable getting Beat position in seconds in real-time. + + Stream/music/wma/cd/any other supported add-on format. + User defined function to receive the beat position values (see ). + User instance data to pass to the callback function. + If successful, is returned, else is returned. Use to get the error code. + This method works on real-time (buffered) as well as on decoding channels and might also be used together with Tempo channels. + must be called at the end to free the real-time beat position callback and resources. + Note: You should call after you have changed the position of the stream when called from a "mixtime" . + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + Get all the beat positions of the first minute of a track: + + private BPMBEATPROC _beatProc; + ... + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_DEFAULT); + _beatProc = new BPMBEATPROC(MyBeatProc); + BassFx.BASS_FX_BPM_BeatCallbackSet(stream, _beatProc, IntPtr.Zero); + Bass.BASS_ChannelPlay(stream, false); + ... + private void MyBeatProc(int channel, double beatpos, IntPtr user) + { + Console.WriteLine("Beat at: {0}", beatpos); + } + + + Private _beatProc As BPMBEATPROC + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_DEFAULT) + _beatProc = New BPMBEATPROC(AddressOf MyBeatProc) + BassFx.BASS_FX_BPM_BeatCallbackSet(stream, _beatProc, IntPtr.Zero) + Bass.BASS_ChannelPlay(stream, False) + ... + Private Sub MyBeatProc(channel As Integer, beatpos As Double, user As IntPtr) + Console.WriteLine("Beat at: {0}", beatpos) + End Sub + + + + + + Resets the internal buffers. + + Stream/music/wma/cd/any other supported add-on format. + If successful, is returned, else is returned. Use to get the error code. + + This function flushes the internal buffers of the Beat callback. The Beat callback is automatically reset by , except when called from a "mixtime" . + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + + Set new values for beat detection parameters. + + Stream/music/wma/cd/any other supported add-on format. + Bandwidth in Hz between 0 and samplerate/2 (-1.0f = leave current, default is 10Hz). + The center-frequency in Hz of the band pass filter between 0 and samplerate/2 (-1.0f = leave current, default is 90Hz). + Beat release time in ms. (-1.0f = leave current, default is 20ms). + If successful, is returned, else is returned. Use to get the error code. + + Beat detection is using a Band Pass Filter. A band-pass filter is a device that passes frequencies within a certain range and rejects (attenuates) frequencies outside that range. + So the parameter defines the range around a center-frequency to include in the beat detection algo. + The parameter actually defines the center-frequency of the band pass filter. + Once a beat is detected, the parameter defines the time in ms. in which no other beat will be detected after that just detected beat. + The background is, that often you have kind-of 'double beats' in a drum set. So the should avoid, that a second (quickly repeated beat) beat is detected. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + Get all the beat positions of the first minute of a track: + + private BPMBEATPROC _beatProc; + ... + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_DEFAULT); + _beatProc = new BPMBEATPROC(MyBeatProc); + BassFx.BASS_FX_BPM_BeatCallbackSet(stream, _beatProc, IntPtr.Zero); + BassFx.BASS_FX_BPM_BeatSetParameters(stream, 20f, 110f, 24f); + Bass.BASS_ChannelPlay(stream, false); + ... + private void MyBeatProc(int channel, double beatpos, IntPtr user) + { + Console.WriteLine("Beat at: {0}", beatpos); + } + + + Private _beatProc As BPMBEATPROC + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_DEFAULT) + _beatProc = New BPMBEATPROC(AddressOf MyBeatProc) + BassFx.BASS_FX_BPM_BeatCallbackSet(stream, _beatProc, IntPtr.Zero) + BassFx.BASS_FX_BPM_BeatSetParameters(stream, 20F, 240F, 24F) + Bass.BASS_ChannelPlay(stream, False) + ... + Private Sub MyBeatProc(channel As Integer, beatpos As Double, user As IntPtr) + Console.WriteLine("Beat at: {0}", beatpos) + End Sub + + + + + + Gets the current beat detection parameter values. + + Stream/music/wma/cd/any other supported add-on format. + Current bandwidth in Hz. + Current center-frequency in Hz of the band pass filter. + Current beat release time in ms. + If successful, is returned, else is returned. Use to get the error code. + + Beat detection is using a Band Pass Filter. A band-pass filter is a device that passes frequencies within a certain range and rejects (attenuates) frequencies outside that range. + So the parameter defines the range around a center-frequency to include in the beat detection algo. + The parameter actually defines the center-frequency of the band pass filter. + Once a beat is detected, the parameter defines the time in ms. in which no other beat will be detected after that just detected beat. + The background is, that often you have kind-of 'double beats' in a drum set. So the should avoid, that a second (quickly repeated beat) beat is detected. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + Get the current beat parameters: + + float bandwidth = 0f; + float centerfreq = 0f; + float beat_rtime = 0f; + if (BassFx.BASS_FX_BPM_BeatGetParameters(stream, ref bandwidth, ref centerfreq, ref beat_rtime)) + { + Console.WriteLine("Bandwidth={0}, Center-Freq={1}, Release-Time={2}", bandwidth, centerfreq, beat_rtime); + } + + + Dim bandwidth As Single = 0F + Dim centerfreq As Single = 0F + Dim beat_rtime As Single = 0F + If BassFx.BASS_FX_BPM_BeatGetParameters(stream, bandwidth, centerfreq, beat_rtime) Then + Console.WriteLine("Bandwidth={0}, Center-Freq={1}, Release-Time={2}", bandwidth, centerfreq, beat_rtime) + End If + + + + + + Gets the current beat parameter values. + + Stream/music/wma/cd/any other supported add-on format. + Current bandwidth in Hz (=don't retrieve it). + Current center-frequency of the band pass filter in Hz (=don't retrieve it). + Current beat release time in ms. (=don't retrieve it). + If successful, is returned, else is returned. Use to get the error code. + + Beat detection is using a Band Pass Filter. A band-pass filter is a device that passes frequencies within a certain range and rejects (attenuates) frequencies outside that range. + So the parameter defines the range around a center-frequency to include in the beat detection algo. + The parameter actually defines the center-frequency of the band pass filter. + Once a beat is detected, the parameter defines the time in ms. in which no other beat will be detected after that just detected beat. + The background is, that often you have kind-of 'double beats' in a drum set. So the should avoid, that a second (quickly repeated beat) beat is detected. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + Get the current beat release time only: + + object beat_rtime = 0f; + if (BassFx.BASS_FX_BPM_BeatGetParameters(stream, null, null, beat_rtime)) + { + // beat_rtime must be casted back to a float + Console.WriteLine("Release-Time={0}", (float)beat_rtime); + } + + + Dim beat_rtime As Object = 0F + If BassFx.BASS_FX_BPM_BeatGetParameters(stream, Nothing, Nothing, beat_rtime) Then + ' beat_rtime must be casted back to a float + Console.WriteLine("Release-Time={0}", CSng(beat_rtime)) + End If + + + + + + Free all resources used by a given handle (decode or callback beat). + + Stream/music/wma/cd/any other supported add-on format. + If successful, is returned, else is returned. Use to get the error code. + Used together with or . + Note: If the BASS_FX_FREESOURCE flag is used, this will free the source decoding channel as well. You can't set/get this flag with and . + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + Load BASS and BASS_FX from the application's startup path: + + Bass.LoadMe(); + BassFx.LoadMe(); + ... + // when not used anymore... + BassFx.FreeMe(); + Bass.FreeMe(); + + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + Load BASS and BASS_FX from a different directory: + + Bass.LoadMe( @"C:\Development\BASS\_libs" ); + BassFx.LoadMe( @"C:\Development\BASS\_libs" ); + ... + // when not used anymore... + BassFx.FreeMe(); + Bass.FreeMe(); + + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + BASS_FX BPM/Beat options, to be used with , resp. . + + + + + Decode: No option. + Caution: when used with the Translate methods this flag would be identical to BASS_FX_BPM_X2. + + + + + Decode: Do the processing in a background thread. + If in use, then you can do other stuff while detection's in process. + + + + + Decode: If in use, then will auto multiply bpm by 2 (if BPM < MinBPM*2). + + + + + Decode: Free the source handle as well? + + + + + BASS_FX BPM Translation options, to be used with . + + + + + BPM Translate: Multiply the original BPM value by 2 (may be called only once & will change the original BPM as well!). + + + + + BPM Translate: BPM value to Frequency. + + + + + BPM Translate: Frequency to BPM value. + + + + + BPM Translate: Percents to BPM value. + + + + + BPM Translate: BPM value to Percents. + + + + + BASS_FX Reverse Playback directions, to be used with the BASS_ATTRIB_REVERSE_DIR attribute. + + + + + Playing in reverse direction. + + + + + Playing in forward direction. + + + + + DSP channels flags. + + + Multi-channel order of each channel is as follows: + + 3 channelsleft-front, right-front, center. + 4 channelsleft-front, right-front, left-rear/side, right-rear/side. + 6 channels (5.1)left-front, right-front, center, LFE, left-rear/side, right-rear/side. + 8 channels (7.1)left-front, right-front, center, LFE, left-rear/side, right-rear/side, left-rear center, right-rear center. + + + + + + All channels at once (as by default). + + + + + Disable an effect for all channels (resp. set the global volume of the effect). + + + + + left-front channel + + + + + right-front channel + + + + + Channel 3: depends on the multi-channel source (see above info). + + + + + Channel 4: depends on the multi-channel source (see above info). + + + + + Channel 5: depends on the multi-channel source (see above info). + + + + + Channel 6: depends on the multi-channel source (see above info). + + + + + Channel 7: depends on the multi-channel source (see above info). + + + + + Channel 8: depends on the multi-channel source (see above info). + + + + + Channel 9: depends on the multi-channel source (see above info). + + + + + Channel 10: depends on the multi-channel source (see above info). + + + + + Channel 11: depends on the multi-channel source (see above info). + + + + + Channel 12: depends on the multi-channel source (see above info). + + + + + Channel 13: depends on the multi-channel source (see above info). + + + + + Channel 14: depends on the multi-channel source (see above info). + + + + + Channel 15: depends on the multi-channel source (see above info). + + + + + Channel 16: depends on the multi-channel source (see above info). + + + + + Channel 17: depends on the multi-channel source (see above info). + + + + + Channel 18: depends on the multi-channel source (see above info). + + + + + Channel 19: depends on the multi-channel source (see above info). + + + + + Channel 20: depends on the multi-channel source (see above info). + + + + + Channel 21: depends on the multi-channel source (see above info). + + + + + Channel 22: depends on the multi-channel source (see above info). + + + + + Channel 23: depends on the multi-channel source (see above info). + + + + + Channel 24: depends on the multi-channel source (see above info). + + + + + Channel 25: depends on the multi-channel source (see above info). + + + + + Channel 26: depends on the multi-channel source (see above info). + + + + + Channel 27: depends on the multi-channel source (see above info). + + + + + Channel 28: depends on the multi-channel source (see above info). + + + + + Channel 29: depends on the multi-channel source (see above info). + + + + + Channel 30: depends on the multi-channel source (see above info). + + + + + BASS_BFX BiQuad filters. Defines within the structure which BiQuad filter should be used. + + + + + BiQuad Lowpass filter. + + + + + BiQuad Highpass filter. + + + + + BiQuad Bandpass filter. + + + + + BiQuad Bandpass Q filter. + + + + + BiQuad Notch filter. + + + + + BiQuad All-Pass filter. + + + + + BiQuad Peaking EQ filter. + + + + + BiQuad Low-Shelf filter. + + + + + BiQuad High-Shelf filter. + + + + + Used with , and to retrieve and set the parameters of the DSP effect Swap/Remap/Downmix. + + + This effect mixes those channels together which are specified in the 'lChannel' array. + Where each array element represent the target channel (0=CHAN1, 1=CHAN2 etc.) it's value represents the source channels which should be mixed together. + If you set a BASS_BFX_CHANNONE flag on a channel, then it will be muted. + This allows you to either downmix, remap or swap any channels with/to any channel. + Example 1: Downmix Channel 1 with Channel 5 and put it in Channel 1 + + lChannel[0] = BASSFXChan.BASS_BFX_CHAN1 | BASSFXChan.BASS_BFX_CHAN5 + + + Example 2: Swap channel 1 and channel 2 + + lChannel[0] = BASSFXChan.BASS_BFX_CHAN2 + lChannel[1] = BASSFXChan.BASS_BFX_CHAN1 + + + Example 3: Duplicate channel 1 to channel 2 + + lChannel[0] = BASSFXChan.BASS_BFX_CHAN1 + lChannel[1] = BASSFXChan.BASS_BFX_CHAN1 + + + Example 4: Remap channel 1 so it will be in channel 2 and 3 + + lChannel[0] = BASSFXChan.BASS_BFX_CHANNONE + lChannel[1] = BASSFXChan.BASS_BFX_CHAN1 + lChannel[2] = BASSFXChan.BASS_BFX_CHAN1 + + + Example 5: Downmix 5.1 to Stereo + + lChannel[0] = BASSFXChan.BASS_BFX_CHAN1 | BASSFXChan.BASS_BFX_CHAN3 | BASSFXChan.BASS_BFX_CHAN5 + lChannel[1] = BASSFXChan.BASS_BFX_CHAN2 | BASSFXChan.BASS_BFX_CHAN4 | BASSFXChan.BASS_BFX_CHAN6 + lChannel[2] = BASSFXChan.BASS_BFX_CHANNONE + lChannel[3] = BASSFXChan.BASS_BFX_CHANNONE + lChannel[4] = BASSFXChan.BASS_BFX_CHANNONE + lChannel[5] = BASSFXChan.BASS_BFX_CHANNONE + + + Multi-channel index is as follows: + + Mono0=left. + Stereo0=left, 1=right. + 3 channels0=left-front, 1=right-front, 2=center. + 4 channels0=left-front, 1=right-front, 2=left-rear/side, 3=right-rear/side. + 6 channels (5.1)0=left-front, 1=right-front, 2=center, 3=LFE, 4=left-rear/side, 5=right-rear/side. + 8 channels (7.1)0=left-front, 1=right-front, 2=center, 3=LFE, 4=left-rear/side, 5=right-rear/side, 6=left-rear center, 7=right-rear center. + + + + + + + Array of channels to mix together using flag's (lChannel[0]=1st=left, lChannel[0]=2nd=right channel etc.). + + Each value of an element represents a flag specifying the source channels to be mixed/used. + Whereas the element index determines the target channel to put the mixed channels to. + + + + Constructor assigning a linear 1:1 remap (0=CHAN1, 1=CHAN2 etc.). + + The number of channels to use. + + + + Constructor already setting the channel order. + + The variable list of the zero-based channel indexes (1st=0, 2nd=1,...). Each parameter will be applied in exactly this order. + + Swap channels 1 and 2: + + BASS_BFX_MIX swap = new BASS_BFX_MIX(BASSFXChan.BASS_BFX_CHAN2, BASSFXChan.BASS_BFX_CHAN1); + int channel = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_DEFAULT); + int fxMix = Bass.BASS_ChannelSetFX(channel, BASSFXType.BASS_FX_BFX_MIX, 0); + Bass.BASS_FXSetParameters(fxMix, swap); + + + Dim swap As New BASS_BFX_MIX(BASSFXChan.BASS_BFX_CHAN2, BASSFXChan.BASS_BFX_CHAN1) + Dim channel As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_DEFAULT) + Dim fxMix As Integer = Bass.BASS_ChannelSetFX(channel, BASSFXType.BASS_FX_BFX_MIX, 0) + Bass.BASS_FXSetParameters(fxMix, swap) + + + + + + Default Finilizer. + + + + + Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + + + + + Used with , and to retrieve and set the parameters of the DSP effect Echo. + + No multi-channel option, only max. 2 channels (stereo). + This is an echo effect that replays what you have played one or more times after a period of time. It's something like the echoes you might hear shouting against a canyon wall. + The fLevel is the volume of a signal. The lDelay is the delay time in ms. + + + + + Echo level (0...1..n, linear). Default = 0. + + Examples: 0.0 = -unlimited dB, 0.5 = -6dB, 1.0 = 0dB, 2.0 = +6dB + To convert a dB value to a 0-1 linear value, you can do this: + double linear = Math.Pow(10d, dB / 20.0); + + To convert a linear value to a dB value, you can do this: + double dB = 20.0 * Math.Log10(level / 1.0); + + Or use the or methods. + + + + + Delay in ms (1200...30000). Default = 1200ms. + + + + + Default constructor + + + + + Constructor already setting the members. + + Echo level (0...1...n). + Delay in ms (1200...30000). + + + + Used with , and to retrieve and set the parameters of the DSP effect Flanger. + + + Flangers mix a varying delayed signal (usually about 5ms [0.005] to 15ms [0.015]) with the original to produce a series of notches in the frequency response. + The important difference between flanging and phasing is that a flanger produces a large number of notches that are harmonically (musically) related, while a phaser produces a small number of notches that are evenly spread across the frequency spectrum. + With high resonance, you get the "jet plane" effect. + + + + + Ratio of wet (processed) signal to dry (unprocessed) signal (0...1...n, linear, default=1). + + + + + Flanger speed in seconds (0...0.09, [0ms - 90ms]). Default 0.01. + + + + + A flag to define on which channels to apply the effect. + Default: -1 (BASS_BFX_CHANALL) - all channels. + + + + + Default constructor. + + + + + Constructor already setting the members + + Ratio of wet (processed) signal to dry (unprocessed) signal (0...1...n). + Flanger speed in seconds (0...0.09). + + + + Constructor already setting the members. + + Ratio of wet (processed) signal to dry (unprocessed) signal (0...1...n). + Flanger speed in seconds (0...0.09). + The channel control flag defining on which channels the effect should be applied to (a combinbation of ). + + + + Sets the instance members to a preset (WetDry=1, Speed=0.012). + + + + + Used with , and to retrieve and set the parameters of the DSP effect Volume. (L/R for STEREO, L for MONO for both channels). + + Global volume is set to 1.0 [0dB]. Channels volume can't be greater than global volume. + To set a new global volume, set lChannel = 0. + + + + + A flag to define on which channels to apply the effect. 0 (BASS_FX_DSP_CHANNONE) for global volume control. + Default: -1 (BASS_BFX_CHANALL) - all channels. + + + + + Volume of the channel (0..1..n). Default = 1 (no amplification). + + Examples: 0.0 = -unlimited dB, 0.5 = -6dB, 1.0 = 0dB, 2.0 = +6dB + To convert a dB value to a 0-1 linear value, you can do this: + double linear = Math.Pow(10d, dB / 20.0); + + To convert a linear value to a dB value, you can do this: + double dB = 20.0 * Math.Log10(level / 1.0); + + Or use the or methods. + + + + + Default constructor. + + + + + Constructor already setting the members. + + Volume of all channel (0..1..n). + The volume is a float value between 0.0 (silence) and 1.0 (full volume, no amplification). A value above 1.0 indicates an amplification, which might cause distortion, if the original sound gets too lound and might needs to be clipped later. + + + + Constructor already setting the members. + + Volume of all channel (0..1..n). + The channel control flag defining on which channels the effect should be applied to (a combinbation of ). + The volume is a float value between 0.0 (silence) and 1.0 (full volume, no amplification). A value above 1.0 indicates an amplification, which might cause distortion, if the original sound gets too lound and might needs to be clipped later. + + + + Used with , and to retrieve and set the parameters of the DSP effect Peaking equalizer. + + + Setting up a multi-band EQ: + + private int _fxEQ; + ... + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_SAMPLE_FLOAT); + SetBFX_EQ(stream); + ... + // increase the treble by +6bB + UpdateFX(2, 6f); + ... + + private void SetBFX_EQ(int channel) + { + // set peaking equalizer effect with no bands + _fxEQ = Bass.BASS_ChannelSetFX(channel, BASSFXType.BASS_FX_BFX_PEAKEQ, 0); + + // setup the EQ bands + BASS_BFX_PEAKEQ eq = new BASS_BFX_PEAKEQ(); + eq.fQ = 0f; + eq.fBandwidth = 2.5f; + eq.lChannel = BASSFXChan.BASS_BFX_CHANALL; + + // create 1st band for bass + eq.lBand = 0; + eq.fCenter = 125f; + Bass.BASS_FXSetParameters(_fxEQ, eq); + UpdateFX(0, 0f); + + // create 2nd band for mid + eq.lBand = 1; + eq.fCenter = 1000f; + Bass.BASS_FXSetParameters(_fxEQ, eq); + UpdateFX(1, 0f); + + // create 3rd band for treble + eq.lBand = 2; + eq.fCenter = 8000f; + Bass.BASS_FXSetParameters(_fxEQ, eq); + UpdateFX(2, 0f); + } + + private void UpdateFX(int band, float gain) + { + BASS_BFX_PEAKEQ eq = new BASS_BFX_PEAKEQ(); + // get values of the selected band + eq.lBand = band; + Bass.BASS_FXGetParameters(_fxEQ, eq); + eq.fGain = gain; + Bass.BASS_FXSetParameters(_fxEQ, eq); + } + + + Private _fxEQ As Integer + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0L.ToUInt32(), 0L.ToUInt32(), BASSFlag.BASS_SAMPLE_FLOAT) + SetBFX_EQ(stream) + ... + ' increase the treble by +6bB + UpdateFX(2, 6F) + ... + + Private Sub SetBFX_EQ(channel As Integer) + ' set peaking equalizer effect with no bands + _fxEQ = Bass.BASS_ChannelSetFX(channel, BASSFXType.BASS_FX_BFX_PEAKEQ, 0) + + ' setup the EQ bands + Dim eq As New BASS_BFX_PEAKEQ() + eq.fQ = 0F + eq.fBandwidth = 2.5F + eq.lChannel = BASSFXChan.BASS_BFX_CHANALL + + ' create 1st band for bass + eq.lBand = 0 + eq.fCenter = 125F + Bass.BASS_FXSetParameters(_fxEQ, eq) + UpdateFX(0, 0F) + + ' create 2nd band for mid + eq.lBand = 1 + eq.fCenter = 1000F + Bass.BASS_FXSetParameters(_fxEQ, eq) + UpdateFX(1, 0F) + + ' create 3rd band for treble + eq.lBand = 2 + eq.fCenter = 8000F + Bass.BASS_FXSetParameters(_fxEQ, eq) + UpdateFX(2, 0F) + End Sub + + Private Sub UpdateFX(band As Integer, gain As Single) + Dim eq As New BASS_BFX_PEAKEQ() + ' get values of the selected band + eq.lBand = band + Bass.BASS_FXGetParameters(_fxEQ, eq) + eq.fGain = gain + Bass.BASS_FXSetParameters(_fxEQ, eq) + End Sub + + + + + + Number of bands (0...n), more bands means more memory and cpu usage. Default = 0. + + + + + Bandwidth in octaves (0.1...4...n), Q is not in use (fBandwidth has priority over fQ). Default = 1 (0=not in use). + In most cases users should use the minimum of 0.5 octave. + The bandwidth in octaves (between -3 dB frequencies for BPF and notch or between midpoint (dBgain/2) gain frequencies for peaking EQ). + + + + + EE kinda definition of Q (0.1...1...n), if bandwidth is not in use. Default = 0.0 (0=not in use). + + + + + Center frequency in Hz (1Hz...nHz). Default = 1000 (max. is 1/2 of the samplerate). + + Use 'oldcenter*freq/oldfreq' to update the fCenter after changing the samplerate. + + + + Gain in dB (-15...0...+15). Default 0dB. + + + + + A flag to define on which channels to apply the effect. + Default: -1 (BASS_BFX_CHANALL) - all channels. + + + + + Default constructor. + + + + + Constructor already setting the members + + Number of bands (0...n), more bands means more memory and cpu usage. + Bandwidth in octaves (0.1...4), Q is not in use. + EE kinda definition of Q (0...1...n), bandwidth is not in use. + Center frequency in Hz (1...n). + Gain in dB (-15...0...+15). + + + + Constructor already setting the members + + Number of bands (0...n), more bands means more memory and cpu usage. + Bandwidth in octaves (0.1...4), Q is not in use. + EE kinda definition of Q )0...1...n), bandwidth is not in use. + Center frequency in Hz (1...n). + Gain in dB (-15...0...+15). + The channel control flag defining on which channels the effect should be applied to (a combinbation of ). + + + + Used with , and to retrieve and set the parameters of the DSP effect Reverb. + + No multi-channel option, only max. 2 channels (stereo). + Reverb is the sound you hear in a room with hard surfaces (such as your bathroom) where sound bounces around the room for a while after the initial sound stops. This effect takes a lot of computing power to reproduce well. + Reverb is actually made up of a very large number of repeats, with varying levels and tones over time. Reverbs usually offer you a choice of different algorithm to simulate different environments such as different sized rooms and halls, studio effects such as plate, chamber and reverse * reverbs, and sometimes emulations of guitar spring reverbs. + The fLevel is the volume of a signal. The lDelay is the delay time in ms. + + + + + Reverb level (0...1...n, linear). Default = 0. + + Examples: 0.0 = -unlimited dB, 0.5 = -6dB, 1.0 = 0dB, 2.0 = +6dB + To convert a dB value to a 0-1 linear value, you can do this: + double linear = Math.Pow(10d, dB / 20.0); + + To convert a linear value to a dB value, you can do this: + double dB = 20.0 * Math.Log10(level / 1.0); + + Or use the or methods. + + + + + Delay in ms (1200...10000). Default = 1200ms. + + + + + Default constructor + + + + + Constructor already setting the members + + Reverb level (0...1...n). + Delay in ms (1200...10000). + + + + Used with , and to retrieve and set the parameters of the DSP effect Low pass filter. + + + + + Resonance (0.01...10). Default = 2. + + + + + Cut-off frequency in Hz (1...info.freq/2). Default = 200Hz. + + + + + A flag to define on which channels to apply the effect. + Default: -1 (BASS_BFX_CHANALL) - all channels. + + + + + Default constructor + + + + + Constructor already setting the members + + Resonance (0.01...10). + Cut-off frequency in Hz (1...info.freq/2). + + + + Constructor already setting the members + + Resonance (0.01...10). + Cut-off frequency in Hz (1...info.freq/2). + The channel control flag defining on which channels the effect should be applied to (a combinbation of ). + + + + Used with , and to retrieve and set the parameters of the DSP effect Dynamic amplification. + + + + + Target volume level (0<...1, linear). Default = 1.0 (0dB). + + Examples: 0.0 = -unlimited dB, 0.5 = -6dB, 1.0 = 0dB + To convert a dB value to a 0-1 linear value, you can do this: + double linear = Math.Pow(10d, dB / 20.0); + + To convert a linear value to a dB value, you can do this: + double dB = 20.0 * Math.Log10(level / 1.0); + + Or use the or methods. + + + + + Quiet volume level (0...1, linear). Default = 0. + + Examples: 0.0 = -unlimited dB, 0.5 = -6dB, 1.0 = 0dB + To convert a dB value to a 0-1 linear value, you can do this: + double linear = Math.Pow(10d, dB / 20.0); + + To convert a linear value to a dB value, you can do this: + double dB = 20.0 * Math.Log10(level / 1.0); + + Or use the or methods. + + + + + Amplification adjustment rate (0...1, linear), e.g. 0.02. Default = 0. + + + + + Amplification level (0...1...n, linear). Default = 0. + + Examples: 0.0 = -unlimited dB, 0.5 = -6dB, 1.0 = 0dB, 2.0 = +6dB + To convert a dB value to a 0-1 linear value, you can do this: + double linear = Math.Pow(10d, dB / 20.0); + + To convert a linear value to a dB value, you can do this: + double dB = 20.0 * Math.Log10(level / 1.0); + + Or use the or methods. + + + + + Delay in seconds before increasing level (0...n, linear). Default = 0. + + + + + A flag to define on which channels to apply the effect. + Default: -1 (BASS_BFX_CHANALL) - all channels. + + + + + Default constructor + + + + + Constructor already setting the members + + Target volume level (0<...1) + Quiet volume level (0...1) + Amplification adjustment rate (0...1) + Amplification level (0...1...n) + Delay in seconds before increasing level (0...n) + + + + Constructor already setting the members + + Target volume level (0<...1) + Quiet volume level (0...1) + Amplification adjustment rate (0...1) + Amplification level (0...1...n) + Delay in seconds before increasing level (0...n) + The channel control flag defining on which channels the effect should be applied to (a combinbation of ). + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Used with , and to retrieve and set the parameters of the DSP effect Auto wah. + + + The effect implements the auto-wah by using 4-stage phaser effect which moves a peak in the frequency response up and down the frequency spectrum by amplitude of input signal. + The fDryMix is the volume of input signal and the fWetMix is the volume of delayed signal. The fFeedback sets feedback of auto wah (phaser). The fRate and fRange control how fast and far the frequency notches move. The fRate is the rate of sweep in cycles per second, fRange is the width of sweep in octaves. And the the fFreq is the base frequency of sweep. + + + + + Dry (unaffected) signal mix (-2...+2). Default = 0. + + + + + Wet (affected) signal mix (-2...+2). Default = 0. + + + + + Feedback (-1...+1). Default = 0. + + + + + Rate of sweep in cycles per second (0<...<10). Default = 0. + + + + + Sweep range in octaves (0<...<10). Default = 0. + + + + + Base frequency of sweep range (0<...1000). Default = 0. + + + + + A flag to define on which channels to apply the effect. + Default: -1 (BASS_BFX_CHANALL) - all channels. + + + + + Default constructor + + + + + Constructor already setting the members + + Dry (unaffected) signal mix (-2...+2) + Wet (affected) signal mix (-2...+2) + Feedback (-1...+1) + Rate of sweep in cycles per second (0<...<10) + Sweep range in octaves (0<...<10) + Base frequency of sweep range (0<...1000) + + + + Constructor already setting the members + + Dry (unaffected) signal mix (-2...+2) + Wet (affected) signal mix (-2...+2) + Feedback (-1...+1) + Rate of sweep in cycles per second (0<...<10) + Sweep range in octaves (0<...<10) + Base frequency of sweep range (0<...1000) + The channel control flag defining on which channels the effect should be applied to (a combinbation of ). + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Used with , and to retrieve and set the parameters of the DSP effect Echo 2. + + + This is an echo effect that replays what you have played one or more times after a period of time. It's something like the echoes you might hear shouting against a canyon wall. + The fDryMix is the volume of input signal and the fWetMix is the volume of delayed signal. The fDelay is the delay time in sec. The fFeedback sets how much delay is feed back to the input (for repeating delays). + + + + + Dry (unaffected) signal mix (-2...+2). Default = 0. + + + + + Wet (affected) signal mix (-2...+2). Default = 0. + + + + + Feedback (-1...+1). Default = 0. + + + + + Delay in seconds (0<...6). Default = 0. + + + + + A flag to define on which channels to apply the effect. + Default: -1 (BASS_BFX_CHANALL) - all channels. + + + + + Default constructor + + + + + Constructor already setting the members + + Dry (unaffected) signal mix (-2..+2) + Wet (affected) signal mix (-2..+2) + Feedback (-1..+1) + Delay in seconds (0<..6) + + + + Constructor already setting the members + + Dry (unaffected) signal mix (-2..+2) + Wet (affected) signal mix (-2..+2) + Feedback (-1..+1) + Delay in seconds (0<..6) + The channel control flag defining on which channels the effect should be applied to (a combinbation of ). + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Used with , and to retrieve and set the parameters of the DSP effect Phaser. + + + Phasers use an internal low frequency oscillator to automatically move notches in the frequency response up and down the frequency spectrum. + An important difference between phasing and flanging is that phasers space these notches evenly across the frequency spectrum, while the notches in flanging and chorus are harmonically (musically) related. + You don't hear the notches as such (because they are the frequencies that are removed). + What you hear is the resulting frequency peaks between these notches. Phasing works by mixing the original signal with one that is phase shifted over the frequency spectrum. + For example, a four stage phaser signal (such as this) could be from 0 degrees at 100Hz, shifted to 720 degrees at 5Khz (these extremes are not quite possible practically, but are near enough to explain the effect). + This is how the term phase shifter comes about. A 4 stage phaser has 2 notches with bass response, a central peak, and treble response. + By using resonance to enhance the central peak, you can get a sound similar to an automatic wah. + Using a phaser with lots of stages and setting the resonance high can give a sound similar to flanging, although they are really quite different. + The fDryMix is the volume of input signal and the fWetMix is the volume of delayed signal. + The fFeedback sets feedback of phaser. + The fRate and fRange control how fast and far the frequency notches move. + The fRate is the rate of sweep in cycles per second, fRange is the width of sweep in octaves. + And the the fFreq is the base frequency of sweep. + + + + + Dry (unaffected) signal mix (-2...+2). Default = 0. + + + + + Wet (affected) signal mix (-2...+2). Default = 0. + + + + + Feedback (-1...+1). Default = 0. + + + + + Rate of sweep in cycles per second (0<...<10). Default = 0. + + + + + Sweep range inoctaves (0<...<10). Default = 0. + + + + + Base frequency of sweep range (0<...1000). Default = 0. + + + + + A flag to define on which channels to apply the effect. + Default: -1 (BASS_BFX_CHANALL) - all channels. + + + + + Default constructor + + + + + Constructor already setting the members + + Dry (unaffected) signal mix (-2...+2) + Wet (affected) signal mix (-2...+2) + Feedback (-1...+1) + Rate of sweep in cycles per second (0<...<10) + Sweep range inoctaves (0<...<10) + Base frequency of sweep range (0<...1000) + + + + Constructor already setting the members + + Dry (unaffected) signal mix (-2...+2) + Wet (affected) signal mix (-2...+2) + Feedback (-1...+1) + Rate of sweep in cycles per second (0<...<10) + Sweep range inoctaves (0<...<10) + Base frequency of sweep range (0<...1000) + The channel control flag defining on which channels the effect should be applied to (a combinbation of ). + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Used with , and to retrieve and set the parameters of the DSP effect Echo 3. + + + This is an echo effect that replays what you have played one or more times after a period of time. It's something like the echoes you might hear shouting against a canyon wall. + The fDryMix is the volume of input signal and the fWetMix is the volume of delayed signal. The fDelay is the delay time in sec. + + + + + Dry (unaffected) signal mix (-2...+2). Default = 0. + + + + + Wet (affected) signal mix (-2...+2). Default = 0. + + + + + Delay in seconds (0<...6). Default = 0. + + + + + A flag to define on which channels to apply the effect. + Default: -1 (BASS_BFX_CHANALL) - all channels. + + + + + Default constructor + + + + + Constructor already setting the members + + Dry (unaffected) signal mix (-2..+2) + Wet (affected) signal mix (-2..+2) + Delay in seconds (0<..6) + + + + Constructor already setting the members + + Dry (unaffected) signal mix (-2..+2) + Wet (affected) signal mix (-2..+2) + Delay in seconds (0<..6) + The channel control flag defining on which channels the effect should be applied to (a combinbation of ). + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Used with , and to retrieve and set the parameters of the DSP effect Chorus. + + + True vintage chorus works the same way as flanging. + It mixes a varying delayed signal with the original to produce a large number of harmonically related notches in the frequency response. + Chorus uses a longer delay than flanging, so there is a perception of "spaciousness", although the delay is too short to hear as a distinct slap-back echo. + There is also little or no feedback, so the effect is more subtle. + The fDryMix is the volume of input signal and the fWetMix is the volume of delayed signal. + The fFeedback sets feedback of chorus. + The fRate, fMinSweep and fMaxSweep control how fast and far the frequency notches move. + The fRate is the rate of delay change in millisecs per sec, fMaxSweep-fMinSweep is the range or width of sweep in ms. + + + + + Dry (unaffected) signal mix (-2...+2). Default = 0. + + + + + Wet (affected) signal mix (-2...+2). Default = 0. + + + + + Feedback (-1...+1). Default = 0. + + + + + Minimum delay in ms (0<...6000). Default = 0. + + + + + Maximum delay in ms (0<...6000). Default = 0. + + + + + Rate in ms/s (0<...1000). Default = 0. + + + + + A flag to define on which channels to apply the effect. + Default: -1 (BASS_BFX_CHANALL) - all channels. + + + + + Default constructor + + + + + Constructor already setting the members + + Dry (unaffected) signal mix (-2...+2) + Wet (affected) signal mix (-2...+2) + Feedback (-1...+1) + Minimum delay in ms (0<...6000) + Maximum delay in ms (0<...6000) + Rate in ms/s (0<...1000) + + + + Constructor already setting the members + + Dry (unaffected) signal mix (-2...+2) + Wet (affected) signal mix (-2...+2) + Feedback (-1...+1) + Minimum delay in ms (0<...6000) + Maximum delay in ms (0<...6000) + Rate in ms/s (0<...1000) + The channel control flag defining on which channels the effect should be applied to (a combinbation of ). + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Used with , and to retrieve and set the parameters of the DSP effect All pass filter. + + + The allpass filter has the unique property that it passes all frequencies equally. This property makes it useful in reverberator design because it increases echo density while reducing signal coloration (an allpass filter is NOT transparent to transient signals, as it does have a phase response). The structure of an allpass filter is similar to the comb filter, but it contains an additional feedforward path. In reverb applications, the delay used in an allpass filter is generally measured in milliseconds. This keeps the 'reflections' spaced apart in a similar fashion to a room's impulse response. + The fDelay sets delay for all pass filter. The fGain controls the gain of all pass filter. + + + + + Gain of the all pass filter (-1...+1). Default = 0. + + + + + Delay in seconds (0...6). Default = 0. + + + + + A flag to define on which channels to apply the effect. + Default: -1 (BASS_BFX_CHANALL) - all channels. + + + + + Default constructor + + + + + Constructor already setting the members + + Gain (-1..+1) + Delay in seconds (0..6) + + + + Constructor already setting the members + + Gain (-1..+1) + Delay in seconds (0..6) + The channel control flag defining on which channels the effect should be applied to (a combinbation of ). + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Used with , and to retrieve and set the parameters of the DSP effect Dynamic Range Compressor. + + + Compressors are commonly used in recording to control the level, by making loud passages quieter, and quiet passages louder. + This is useful in allowing a vocalist to sing quiet and loud for different emphasis, and always be heard clearly in the mix. + Compression is generally applied to guitar to give clean sustain, where the start of a note is "squashed" with the gain automatically increased as the not fades away. + Compressors take a short time to react to a picked note, and it can be difficult to find settings that react quickly enough to the volume change without killing the natural attack sound of your guitar. + The fThreshold sets the level above which volume is cut, and below which volume is boosted. + This is usually achieved simply by increasing the internal gain, so it really controls the amount of perceived sustain. + The fAttacktime controls how fast the unit responds to volume increases. + The fReleasetime controls how slowly the unit responds to decreasing volume. + + + + + Compressor threshold (0...+1). Default = 0. + + + + + Attack time in ms (0<...1000). Default = 0. + + + + + Release time in ms (0<...5000). Default = 0. + + + + + A flag to define on which channels to apply the effect. + Default: -1 (BASS_FX_DSP_CHANALL) - all channels. + + + + + Default constructor + + + + + Constructor already setting the members + + Compressor threshold (0...+1) + Attack time in ms (0<...1000) + Release time in ms (0<...5000) + + + + Constructor already setting the members + + Compressor threshold (0...+1) + Attack time in ms (0<...1000) + Release time in ms (0<...5000) + The channel control flag defining on which channels the effect should be applied to (a combinbation of ). + + + + Sets the instance members to a preset. + + + Threshold: -6 dB + Attack: 15ms + Release: 1sec + + + + + Sets the instance members to a preset. + + + Threshold: -2 dB + Attack: 1ms + Release: 500ms + + + + + Sets the instance members to a preset. + + + Threshold: -1 dB + Attack: 20ms + Release: 350ms + + + + + Sets the instance members to a preset. + + + Threshold: -3 dB + Attack: 10ms + Release: 200ms + + + + + Sets the instance members to a preset. + + Threshold: -6 dB + Attack: 5ms + Release: 250ms + + + + Sets the instance members to a preset. + + Threshold: -12 dB + Attack: 2.2ms + Release: 400ms + + + + Used with , and to retrieve and set the parameters of the DSP effect Distortion. + + + Similar to Pre/Post Gain and Drive controls on amps. + They were first introduced as a trick to added color to a guitar's tone. + Usually produced back then by turning the amp all the way up, or slightly pulling out a tube from its socket. + These tones are now today referred to as Overdrives. + Today, there are an almost infinite variety of these effects, and they range in 3 classes: Distortions, Fuzz, and Overdrive. + One common feature to mostly all of these types of pedals is a volume and drive (also noted as distortion, fuzz, gain, ...etc.). + Overdrives are usually a sustain and volume boosting pedal. Used by more traditional rock and country bands. + Next are the Distortions, which range from punk style to death metal screams. They are similar to Overdrives, but have more buzzing quality to them. + Finally, there are the Fuzzes which are more distorted than distortions, but are more mellow and compressed sounding. + Many pedals can be confused within these names, and some may be named other than what they are. + Towards the end of this era, the back-to-back diode pair became popular as a technique to provide soft clipping (with germanium diodes) and hard clipping (with silicon diodes). + Today, overdrive effects usually means soft clipping, where gain is reduced beyond the clipping point, while distortion usually means hard clipping, where the level is fixed beyond the clipping point. + Distortion is a little harder sound, good for rock, while overdrive gives a more natural sound. + The fDrive controls the amount of overdrive. + The fVolume to balance the effect volume with the bypassed level. + It can also be used to boost the signal for solos. + The fDryMix is the volume of input signal and the fWetMix is the volume of distorted signal. + The fFeedback sets feedback of distortion. + + + + + Distortion drive (0...5). Default = 0. + + + + + Dry (unaffected) signal mix (-5...+5). Default = 0. + + + + + Wet (affected) signal mix (-5...+5). Default = 0. + + + + + Feedback (-1...+1). Default = 0. + + + + + Distortion volume (0...+2). Default = 0. + + + + + A flag to define on which channels to apply the effect. + Default: -1 (BASS_BFX_CHANALL) - all channels. + + + + + Default constructor + + + + + Constructor already setting the members + + Distortion drive (0...5) + Dry (unaffected) signal mix (-5...+5) + Wet (affected) signal mix (-5...+5) + Feedback (-1...+1) + Distortion volume (0...+2) + + + + Constructor already setting the members + + Distortion drive (0...5) + Dry (unaffected) signal mix (-5...+5) + Wet (affected) signal mix (-5...+5) + Feedback (-1...+1) + Distortion volume (0...+2) + The channel control flag defining on which channels the effect should be applied to (a combinbation of ). + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Used with , and to retrieve and set the parameters of the DSP effect Dynamic Range Compressor. + + + Dynamic range compression also called DRC, or simply compression, is a process that reduces the dynamic range of an audio signal. + Compression is used during sound recording, live sound reinforcement, and broadcasting to control the level of audio. A compressor is the device used to apply compression. + Compressors are commonly used in recording to control the level, by making loud passages quieter, and quiet passages louder. + This is useful in allowing a vocalist to sing quiet and loud for different emphasis, and always be heard clearly in the mix. + Compression is generally applied to guitar to give clean sustain, where the start of a note is "squashed" with the gain automatically increased as the not fades away. + Compressors take a short time to react to a picked note, and it can be difficult to find settings that react quickly enough to the volume change without killing the natural attack sound of your guitar. + The fThreshold sets the level above which volume is reduced in level while quiet sound are untreated (downward compression). + The fAttack controls how fast the unit responds to volume increases. + The fRelease controls how slowly the unit responds to decreasing volume. + The compressor reduces the gain (level) of an audio signal if its amplitude exceeds a threshold (using RMS sensing with a hard knee). + The amount of gain reduction is determined by a ratio. For example, with a ratio of 4:1, when the (time averaged) input level is 4 dB over the threshold, the output signal level will be 1 dB over the threshold. + The gain (level) has been reduced by 3 dB. When the input level is 8 dB above the threshold, the output level will be 2 dB; a 6 dB gain reduction. + A more specific example for a 4:1 ratio: + Threshold = −10 dB; + Input = −6 dB (4 dB above the threshold); + Output = −9 dB (1 dB above the threshold) + + With any threshold/ratio combination, you could calculate the gain for a 0dB peak like this: + fGain=fThreshold*(1/fRatio-1) + + + + + + Output gain in dB of signal after compression, in the range from -60 to 60. The default value is 5 dB. + + + + + Point in dB at which compression begins, in decibels, in the range from -60 to 0. The default value is -15 dB. + + + + + Compression ratio, in the range from 1 to 100. The default value is 3, which means 3:1 compression. + + + + + Time in ms before compression reaches its full value, in the range from 0.01 to 500. The default value is 20 ms. + + + + + Time (speed) in ms at which compression is stopped after input drops below fThreshold, in the range from 50 to 3000. The default value is 200 ms. + + + + + A flag to define on which channels to apply the effect. + Default: -1 (BASS_BFX_CHANALL) - all channels. + + + + + Default constructor + + + + + Constructor already setting the members. + + Output gain in dB of signal after compression, in the range from -60 to 60. + Point in dB at which compression begins, in decibels, in the range from -60 to 0. + Compression ratio, in the range from 1 to 100. + Time in ms before compression reaches its full value, in the range from 0.01 to 500. + Speed in ms at which compression is stopped after input drops below fThreshold, in the range from 50 to 3000. + The channel control flag defining on which channels the effect should be applied to (a combinbation of ). + + + + Calculates for the current threshold/ratio combination a gain value to roughly achieve a 0 dB peak line. + + Sets fGain=(fThreshold/2)*(1/fRatio-1). + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Used with , and to retrieve and set the parameters of the DSP effect Volume Envelope. + + + Make sure that the first node is at position 0.0. + Envelopes are applied on top of the channel's attributes, as set via . + The final volume is a product of the channel attribute and the envelope. + + + Setting a volume envelope on a source channel: + + int fx = Bass.BASS_ChannelSetFX(source, BASSFXType.BASS_FX_BFX_VOLUME_ENV, 0); + BASS_BFX_VOLUME_ENV ve = new BASS_BFX_VOLUME_ENV( + new BASS_BFX_ENV_NODE(0.0, 1f), + new BASS_BFX_ENV_NODE(5.0, 1f), + new BASS_BFX_ENV_NODE(7.0, 0.5f), + new BASS_BFX_ENV_NODE(12.0, 0.5f), + new BASS_BFX_ENV_NODE(14.0, 1f)); + // which is the same as: + BASS_BFX_ENV_NODE[] en = new BASS_BFX_ENV_NODE[5]; + en[0].pos = 0.0; + en[0].val = 1f; + en[1].pos = 5.0; + en[2].val = 1f; + en[3].pos = 7.0; + en[3].val = 0.5f; + en[4].pos = 12.0; + en[4].val = 0.5f; + en[5].pos = 14.0; + en[5].val = 1f; + ve = new BASS_BFX_VOLUME_ENV(en); + + Bass.BASS_FXSetParameters(fx, ve); + + + Dim fx As Integer = Bass.BASS_ChannelSetFX(source, BASSFXType.BASS_FX_BFX_VOLUME_ENV, 0) + Dim ve As New BASS_BFX_VOLUME_ENV( + New BASS_BFX_ENV_NODE(0.0, 1F), + New BASS_BFX_ENV_NODE(5.0, 1F), + New BASS_BFX_ENV_NODE(7.0, 0.5F), + New BASS_BFX_ENV_NODE(12.0, 0.5F), + New BASS_BFX_ENV_NODE(14.0, 1F)) + ' which is the same as: + Dim en As BASS_BFX_ENV_NODE() = New BASS_BFX_ENV_NODE(4) {} + en(0).pos = 0.0 + en(0).val = 1F + en(1).pos = 5.0 + en(2).val = 1F + en(3).pos = 7.0 + en(3).val = 0.5F + en(4).pos = 12.0 + en(4).val = 0.5F + en(5).pos = 14.0 + en(5).val = 1F + ve = New BASS_BFX_VOLUME_ENV(en) + + Bass.BASS_FXSetParameters(fx, ve) + + Getting a volume envelope from a source channel: + + BASS_BFX_VOLUME_ENV ve = new BASS_BFX_VOLUME_ENV(); + if (Bass.BASS_FXGetParameters(fx, ve)) + { + foreach (BASS_BFX_ENV_NODE node in ve.pNodes) + Console.WriteLine(node); + } + + + Dim ve As New BASS_BFX_VOLUME_ENV() + If Bass.BASS_FXGetParameters(fx, ve) Then + For Each node As BASS_BFX_ENV_NODE In ve.pNodes + Console.WriteLine(node) + Next + End If + + + + + + A flag to define on which channels to apply the effect. + Default: -1 (BASS_BFX_CHANALL) - all channels. + + + + + The number of nodes contained in the pNodes array. + + + + + Follow the source position (default is )? + + If set to , position changes also change the position of the volume envelope. + When it's , the envelope position is never reset. + + + + The array of envelope nodes (the first node must be at position 0.0). + + + + + Default constructor. + + + + + Constructor assigning the number of volume envelope nodes to use. + + The number of volume envelope nodes to use. + + + + Constructor assigning the volume envelope nodes to use. + + The array of volume nodes to use with this instance (the first node must be at position 0.0). + + + + Default Finilizer. + + + + + Implements the IDisposable interface. + + + + + Used within to define one volume envelope node. + + + Envelopes are applied on top of the channel's attributes, as set via . + The final volume is a product of the channel attribute and the envelope. + + + + + The postion of the node in seconds. + + + + + The volume envelope value at the position (0.0=silence, 1.0=max.). + + + + + Constructor to initialize the members. + + The postion of the node in seconds. + The volume envelope value at the position (0.0=silence, 1.0=max.). + + + + A description of the volume envelope node (position, value). + + A description of the volume envelope node (position, value). + + + + Used with , and to retrieve and set the parameters of the DSP effect Dynamic Range Compressor. + + + Dynamic range compression also called DRC, or simply compression, is a process that reduces the dynamic range of an audio signal. + Compression is used during sound recording, live sound reinforcement, and broadcasting to control the level of audio. A compressor is the device used to apply compression. + Compressors are commonly used in recording to control the level, by making loud passages quieter, and quiet passages louder. + This is useful in allowing a vocalist to sing quiet and loud for different emphasis, and always be heard clearly in the mix. + Compression is generally applied to guitar to give clean sustain, where the start of a note is "squashed" with the gain automatically increased as the not fades away. + Compressors take a short time to react to a picked note, and it can be difficult to find settings that react quickly enough to the volume change without killing the natural attack sound of your guitar. + The fThreshold sets the level above which volume is reduced in level while quiet sound are untreated (downward compression). + The fAttack controls how fast the unit responds to volume increases. + The fRelease controls how slowly the unit responds to decreasing volume. + The compressor reduces the gain (level) of an audio signal if its amplitude exceeds a threshold (using RMS sensing with a hard knee). + The amount of gain reduction is determined by a ratio. For example, with a ratio of 4:1, when the (time averaged) input level is 4 dB over the threshold, the output signal level will be 1 dB over the threshold. + The gain (level) has been reduced by 3 dB. When the input level is 8 dB above the threshold, the output level will be 2 dB; a 6 dB gain reduction. + A more specific example for a 4:1 ratio: + Threshold = −10 dB; + Input = −6 dB (4 dB above the threshold); + Output = −9 dB (1 dB above the threshold) + + With any threshold/ratio combination, you could calculate the gain for a 0dB peak like this: + fGain=fThreshold*(1/fRatio-1) + + + + + + Defines which BiQuad filter should be used. + + + + + Cut-off frequency (Center in PEAKINGEQ and Shelving filters) in Hz (1...info.freq/2). Default = 200Hz. + + + + + Gain in dB (-15...0...+15). Default 0dB (used only for PEAKINGEQ and Shelving filters). + + + + + Bandwidth in octaves (0.1...4...n), Q is not in use (fBandwidth has priority over fQ). Default = 1 (0=not in use). + The bandwidth in octaves (between -3 dB frequencies for for BANDPASS and NOTCH or between midpoint (dBgain/2) gain frequencies for PEAKINGEQ). + + + + + EE kinda definition of Q (0.1...1...n), if bandwidth is not in use. Default = 0.0 (0=not in use). + + + + + A shelf slope parameter (linear, used only with Shelving filters) (0...1...n). Default = 0.0. + When fS=1, the shelf slope is as steep as you can get it and remain monotonically increasing or decreasing gain with frequency. + + + + + A flag to define on which channels to apply the effect. + Default: -1 (BASS_BFX_CHANALL) - all channels. + + + + + Default constructor + + + + + Constructor already setting the members. + + The filter to use (one of ). + Cut-off frequency (Center in PEAKINGEQ and Shelving filters) in Hz (1...info.freq/2). + Gain in dB (-15...0...+15). Default 0dB (used only for PEAKINGEQ and Shelving filters). + Bandwidth in octaves (0.1...4...n), Q is not in use (fBandwidth has priority over fQ) (0=not in use). + EE kinda definition of Q (0.1...1...n), if bandwidth is not in use (0=not in use). + A shelf slope parameter (linear, used only with Shelving filters) (0...1...n). + The channel control flag defining on which channels the effect should be applied to (a combinbation of ). + + + + User defined callback function, to get the bpm detection process in percents. + + Channel that the applies to. + The progress of the process in percent (0%..100%). + + NOTE: When you pass an instance of a callback delegate to one of the BASS functions, this delegate object will not be reference counted. + This means .NET would not know, that it might still being used by BASS. The Garbage Collector might (re)move the delegate instance, if the variable holding the delegate is not declared as global. + So make sure to always keep your delegate instance in a variable which lives as long as BASS needs it, e.g. use a global variable or member. + + + + + User defined callback function, to auto get the BPM after each period of time in seconds. + + Handle that the applies to. + The new original bpm value. + The user instance data given when was called. + + NOTE: When you pass an instance of a callback delegate to one of the BASS functions, this delegate object will not be reference counted. + This means .NET would not know, that it might still being used by BASS. The Garbage Collector might (re)move the delegate instance, if the variable holding the delegate is not declared as global. + So make sure to always keep your delegate instance in a variable which lives as long as BASS needs it, e.g. use a global variable or member. + + + + + User defined callback function, to get the Beat position in seconds. + + Handle that the or has applied to. + The exact beat position in seconds. + The user instance data given when or was called. + + NOTE: When you pass an instance of a callback delegate to one of the BASS functions, this delegate object will not be reference counted. + This means .NET would not know, that it might still being used by BASS. The Garbage Collector might (re)move the delegate instance, if the variable holding the delegate is not declared as global. + So make sure to always keep your delegate instance in a variable which lives as long as BASS needs it, e.g. use a global variable or member. + + + + + BASS.NET API wrapper for BASSCD.DLL + Requires: basscd.dll - CD Audio Tracks (CD) Add-On - available @ www.un4seen.com. + + + BASSCD is an extension to the BASS audio library, enabling the streaming and ripping of CD audio tracks. + The CD format is used in very much the same way as any of the built-in BASS stream formats - simply call the CD stream creation function instead of the BASS built-in functions. The BASS plugin system (see ) is also supported for CDA files. + Plus there are many additional CD drive, digital as well as analog related methods. + + + + + NOT used - all members are static! + + + + + Sets the interface to use to access CD drives + + The interface to use, which can be one of the following (see ): + + BASS_CD_IF_AUTOAutomatically detect an available interface. The interfaces are checked in the order that they are listed here. For example, if both SPTI and ASPI are available, SPTI will be used. + BASS_CD_IF_SPTISCSI Pass-Through Interface. This is only available on NT-based Windows, not Windows 9x, and generally only to administrator user accounts, not limited/restricted user accounts. + BASS_CD_IF_ASPIAdvanced SCSI Programming Interface. This is the only interface available on Windows 9x, and can also be installed on NT-based Windows. + BASS_CD_IF_WIOWindows I/O. Like SPTI, this is only available on NT-based Windows, but it is also available to limited/restricted user accounts. Some features are not available via this interface, notably sub-channel data reading and read speed control (except on Vista or newer). Door status detection is also affected. + + + If successful, the interface being used is returned, else -1 is returned. Use to get the error code. + + The interface can be changed at any time, but any existing CD streams will be freed in doing so. + The current interface can also be reinitialized, to detect any newly connected drives. + Use of this function is optional. If it is not used, BASSCD will automatically detect an available interface. + + + ERROR CODEDescription + BASS_ERROR_ILLPARAM is invalid. + BASS_ERROR_NOTAVAILThe interface is not available, or has no drives available. + + + + + + + Retrieves information on a drive. + + The drive to get info on... 0 = the first drive. + An instance of the class to store the information at. + If successful, is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + + + + + + BASS_CD_INFO info = new BASS_CD_INFO(); + if ( BassCd.BASS_CD_GetInfo(0, info) ) + Console.WriteLine( info.ToString() ); + + + Dim info As New BASS_CD_INFO() + If BassCd.BASS_CD_GetInfo(0, info) Then + Console.WriteLine(info.ToString()) + End If + + Check if the first drive can read CD-TEXT: + + bool canReadCDText = false; + BASS_CD_INFO info = new BASS_CD_INFO(); + if (BassCd.BASS_CD_GetInfo(0, info) && info.cdtext) + { + canReadCDText = true; + } + + + Dim canReadCDText As Boolean = False + Dim info As New BASS_CD_INFO() + If BassCd.BASS_CD_GetInfo(0, info) AndAlso info.cdtext Then + canReadCDText = True + End If + + + + + + Retrieves information on a drive. + + The drive to get info on... 0 = the first drive. + An instance of the class on success - or on error. + + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + + + + + + BASS_CD_INFO info = BassCd.BASS_CD_GetInfo(0); + if ( info != null ) + Console.WriteLine( info.ToString() ); + + + Dim info As BASS_CD_INFO = BassCd.BASS_CD_GetInfo(0) + If Not (info Is Nothing) Then + Console.WriteLine(info.ToString()) + End If + + + + + + Retrieves information on a drive. + + The drive to get info on... 0 = the first drive. + Release the drive after obtaining the info? + If set, will be called right after (which might be required with some drivers). + + An instance of the class on success - or on error. + + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + + + + + + BASS_CD_INFO info = BassCd.BASS_CD_GetInfo(0); + if ( info != null ) + Console.WriteLine( info.ToString() ); + + + Dim info As BASS_CD_INFO = BassCd.BASS_CD_GetInfo(0) + If Not (info Is Nothing) Then + Console.WriteLine(info.ToString()) + End If + + + + + + Returns all available CD drive information. + + An array of representing the available CD drives. + Uses internally. + The index of the returned information equals the drive number, which might be used with any other BassCd method. + + + + + Returns all available CD drive information. + + Release the drive(s) after obtaining the info? + If set, will be called right after (which might be required with some drivers). + + An array of representing the available CD drives. + Uses internally. + The index of the returned information equals the drive number, which might be used with any other BassCd method. + + + + + Returns the total number of available CD drives. + + Number of CD drives available. + Uses internally. + + + + Returns the total number of available CD drives. + + Release the drive(s) after obtaining the info? + If set, will be called right after (which might be required with some drivers). + + Number of CD drives available. + Uses internally. + + + + Opens, closes, locks or unlocks a drive door. + + The drive... 0 = the first drive. + The action to perform... one of the following (see ): + + BASS_CD_DOOR_CLOSEClose the door. + BASS_CD_DOOR_OPENOpen the door. + BASS_CD_DOOR_LOCKLock the door. + BASS_CD_DOOR_UNLOCKUnlock the door. + + + If successful, is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_ILLPARAM is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! Could be that the door is locked. + + + + + Open the CD door of the first drive: + + BassCd.BASS_CD_Door( 0, BASSCDDoor.BASS_CD_DOOR_OPEN ); + + + BassCd.BASS_CD_Door( 0, BASSCDDoor.BASS_CD_DOOR_OPEN ) + + + + + + Checks if a drive door/tray is open. + + The drive to check... 0 = the first drive. + is returned if the door is open, else is returned. + It is not possible to get the drive's current door status via the WIO interface. + So the last known status will be returned in that case, which may not be accurate if the door has been opened or closed by another application, or manually. + + + + Checks if a drive door/tray is locked. + + The drive to check... 0 = the first drive. + is returned if the door is locked, else is returned. + It is not possible to get the drive's current door status via the WIO interface. + So the last known status will be returned in that case, which may not be accurate if the door has been opened or closed by another application. + + + + Releases a drive to allow other applications to access it. + + The drive to release... 0 = the first drive. + If successful, then is returned, else is returned. Use to get the error code. + + When using the SPTI interface, some applications may require BASSCD to release a CD drive before the app is able to use it. + After a drive has been released, BASSCD will attempt to re-acquire it in the next BASSCD function call made on it. + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_NOTAVAILThe ASPI interface is being used. + + + + + + + Retrieves the current read speed setting of a drive. + + The drive... 0 = the first drive. + If successful, the read speed (in KB/s) is returned, else -1 is returned. Use to get the error code. + Divide the speed by 176.4 to get the real-time speed multiplier, eg. 5645 / 176.4 = "32x speed". + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_NOTAVAILThe read speed is unavailable. + + + + + + + Retrieves the current read speed factor of a drive. + + The drive... 0 = the first drive. + If successful, the read speed factor (e.g. 32x) is returned, else -1 is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_NOTAVAILThe read speed is unavailable. + + + + + + + Sets the read speed of a drive in KB/s. + + The drive... 0 = the first drive. + The speed, in KB/s. + If successful, is returned, else is returned. Use to get the error code. + + The speed is automatically restricted (rounded down) to what's supported by the drive, so may not be exactly what was requested. can be used to check that. + The maximum supported speed can be retrieved via . + To use a real-time speed multiplier, multiply it by 176.4 (and round up) to get the KB/s speed to use with this function, eg. "32x speed" = 32 * 176.4 = 5645. + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Sets the read speed of a drive. + + The drive... 0 = the first drive. + The speed factor multiplier, e.g. 32.0 for 32x. + If successful, is returned, else is returned. Use to get the error code. + + The speed is automatically restricted (rounded down) to what's supported by the drive, so may not be exactly what was requested. can be used to check that. + The maximum supported speed can be retrieved via . + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Gets the read cache of a CD drive. + + The drive... 0 = the first drive. + Gets the current read cache value. + + + + Sets the read cache of a CD drive. + + The drive... 0 = the first drive. + to enable the read cache - to disable it. + If successful, is returned, else is returned. Use to get the error code. + + + + Sets the read offset of a drive. + + The drive... 0 = the first drive. + The offset (in samples; bytes/4) to set. + If successful, is returned, else is returned. Use to get the error code. + + This function can be used to compensate for the fact that most drives will read audio data from CDs at a slight offset from where they ideally should. + Different drive models will have differing offsets, a list of which can be found at AccurateRip. + When a negative offset is used, reading the beginning of the first track will require accessing the lead-in, and when a positive offset is used, reading the end of the last track will require accessing the lead-out. + The drive may not support that (overreading), in which case those parts will be replaced with silence. + Changes do not affect an existing CD stream, unless is called (and any sub-channel/C2 reading is using a ). + + + + + Checks if there is a CD ready in a drive. + + The drive to check... 0 = the first drive. + If there is a CD ready in the drive, then is returned, else is returned. + This function only returns once there's a CD in the drive, and it's ready to be accessed. + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + + + + + + + + + + + + + + + Retrieves identification info from the CD in a drive. + + The drive... 0 = the first drive. + The identification to retrieve, one of the following (see ): + + BASS_CDID_UPCReturns the catalog number of the CD. The number uses UPC/EAN-code (BAR coding). This might not be available for all CDs. + BASS_CDID_CDDBProduces a CDDB identifier. This can be used to get details on the CD's contents from a CDDB server. + BASS_CDID_CDDB_QUERYSends a "query" command to the configured CDDB server (see ) to get a list of matching entries for the CD's CDDB identifier. The contents of each entry can be retrieved via the BASS_CDID_CDDB_READ option. + BASS_CDID_CDDB_READ + entrySends a "read" command to the configured CDDB server (see ) to get a database entry for the CD's CDDB identifier... 0 = first entry. + BASS_CDID_CDDB_READ_CACHEReturns the cached CDDB "read" command response, if there is one. + BASS_CDID_CDDB2Produces a CDDB2 identifier. This can be used to get details on the CD's contents from a CDDB2 server. + BASS_CDID_CDPLAYERProduces an identifier that can be used to lookup CD details in the CDPLAYER.INI file, located in the Windows directory. + BASS_CDID_MUSICBRAINZProduces an identifier that can be used to get details on the CD's contents from MusicBrainz. + BASS_CDID_ISRC + trackReturns the International Standard Recording Code of the track... 0 = first track. This might not be available for all CDs. + Use for a more convenient way to read the ISRC. + + + If an error occurs, is returned, use to get the error code. If successful, the identication info is returned. + + BASS_CDID_TEXT is not supported with this overload (see ). + The returned identification string will remain in memory until the next call to this function, when it will be overwritten by the next result. + If you need to keep the contents of an identification string, you should copy it before calling this function again. Exceptions to that are BASS_CDID_CDDB_QUERY and BASS_CDID_CDDB_READ responses, which are cached separately per-drive. + A BASS_CDID_CDDB_QUERY response remains cached while the same CD is in the drive, and a BASS_CDID_CDDB_READ response is cached until a different database entry is requested. + The CDDB caches are also cleared whenever the CDDB server is changed via the config option. + When requesting CDDB identification, the string returned is what should be used in a CDDB query. The command sent to the CDDB server would be "cddb query <the returned string>". + If successful, that results in a list of matching CDs, which the contents of can be requested using the "cddb read" command. + That is what the BASS_CDID_CDDB_QUERY and BASS_CDID_CDDB_READ options do. + See www.cddb.com and www.freedb.org for more information on using a CDDB server. + When requesting MUSICBRAINZ see www.musicbrainz.org for details. + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_NOCDThere's no CD in the drive. + BASS_ERROR_ILLPARAM is invalid. + BASS_ERROR_NOTAVAILThe CD does not have a UPC, ISRC or CD-TEXT info, or the BASS_CDID_CDDB_READ entry number is not valid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Get a CDDB2 string from your first drive: + + string cddb2 = BASS_CD_GetID(0, BASSCDId.BASS_CDID_CDDB2); + + + Dim cddb2 As String = BASS_CD_GetID(0, BASSCDId.BASS_CDID_CDDB2) + + + + + + Returns the International Standard Recording Code of a track. + + The drive... 0 = the first drive. + The track... 0 = the first track. + If an error occurs, is returned, use to get the error code. If successful, the ISRC is returned. + + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_NOCDThere's no CD in the drive. + BASS_ERROR_ILLPARAM is invalid. + BASS_ERROR_NOTAVAILThe CD does not have a UPC, ISRC or CD-TEXT info. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Retrieves CD-Text identification info from the CD in a drive (BASS_CDID_TEXT). + + The drive... 0 = the first drive. + If an error occurs, is returned, use to get the error code. + If successful, a string array of all CD-Text tags is returned. + CD-TEXT tags: + When requesting CD-TEXT, the tags are returned in the form of "tag=text". + The following is a list of all the possible tags. Where <t> is shown, that represents the track number, with "0" being the whole disc/album. For example, "TITLE0" is the album title, while "TITLE1" is the title of the first track. + + TITLE<t>The track (or album) title. + PERFORMER<t>The performer(s), artist(s). + SONGWRITER<t>The song writer(s). + COMPOSER<t>The composer(s). + ARRANGER<t>The arranger(s). + MESSAGE<t>Message. + GENRE<t>Genre. + ISRC<t>International Standard Recording Code (ISRC) of the track... <t> is never 0. + UPCUPC/EAN code of the album. + DISCIDDisc identification information. + + + + The returned identification string will remain in memory until the next call to this function, when it'll be overwritten by the next result. If you need to keep the contents of an identification string, then you should copy it before calling this function again. + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_NOCDThere's no CD in the drive. + BASS_ERROR_ILLPARAM is invalid. + BASS_ERROR_NOTAVAILThe CD does not have a UPC, ISRC or CD-TEXT info. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + List all CD-Text tags of your first drive: + + string[] cdText = BASS_CD_GetIDText(0); + if (cdText != null) + { + foreach (string tag in cdText) + Console.Writeln( tag ); + } + + + Dim cdText As String() = BASS_CD_GetIDText(0) + If Not (cdText Is Nothing) Then + Dim tag As String + For Each tag In cdText + Console.Writeln(tag) + Next tag + End If + + + + + + Retrieves the TOC from the CD in a drive. + + The drive to get info on... 0 = the first drive. + Optionally, the following (see ): + + BASS_CD_TOC_LBAGet the track start address in LBA form. + BASS_CD_TOC_TIMEGet the track start address in time form. + + + An instance of the class to store the information at. + If successful, is returned, else is returned. Use to get the error code. + This function gives the TOC in the form that it is delivered by the drive, except that the byte order may be changed to match the system's native byte order (the TOC is originally big-endian). + + + ERROR CODEDescription + BASS_ERROR_DEVICE is not valid. + BASS_ERROR_NOCDThere's no CD in the drive. + + + + + Get a CD's TOC: + + BASS_CD_TOC toc = new BASS_CD_TOC(); + if (BassCd.BASS_CD_GetTOC(0, BASSCDTOCMode.BASS_CD_TOC_TIME, toc)) + { + Console.WriteLine(toc.ToString()); + // list the TOC_TRACKs + foreach (BASS_CD_TOC_TRACK track in toc.tracks) + { + Console.WriteLine(track.ToString()); + } + } + + + Dim toc As New BASS_CD_TOC() + If BassCd.BASS_CD_GetTOC(0, BASSCDTOCMode.BASS_CD_TOC_TIME, toc) Then + Console.WriteLine(toc.ToString()) + ' list the TOC_TRACKs + For Each track As BASS_CD_TOC_TRACK In toc.tracks + Console.WriteLine(track.ToString()) + Next + End If + + + + + + Retrieves the TOC from the CD in a drive. + + The drive to get info on... 0 = the first drive. + Optionally, the following (see ): + + BASS_CD_TOC_LBAGet the track start address in LBA form. + BASS_CD_TOC_TIMEGet the track start address in time form. + + + If successful, an instance of the class is returned, else is returned. Use to get the error code. + This function gives the TOC in the form that it is delivered by the drive, except that the byte order may be changed to match the system's native byte order (the TOC is originally big-endian). + + + ERROR CODEDescription + BASS_ERROR_DEVICE is not valid. + BASS_ERROR_NOCDThere's no CD in the drive. + + + + + Get a CD's TOC: + + BASS_CD_TOC toc = BassCd.BASS_CD_GetTOC(0, BASSCDTOCMode.BASS_CD_TOC_TIME); + if (toc != null) + { + Console.WriteLine(toc.ToString()); + // list the TOC_TRACKs + foreach (BASS_CD_TOC_TRACK track in toc.tracks) + { + Console.WriteLine(track.ToString()); + } + } + + + Dim toc As BASS_CD_TOC = BassCd.BASS_CD_GetTOC(0, BASSCDTOCMode.BASS_CD_TOC_TIME) + If toc IsNot Nothing Then + Console.WriteLine(toc.ToString()) + ' list the TOC_TRACKs + For Each track As BASS_CD_TOC_TRACK In toc.tracks + Console.WriteLine(track.ToString()) + Next + End If + + + + + + Retrieves the number of tracks on the CD in a drive. + + The drive... 0 = the first drive. + If an error occurs, -1 is returned, use to get the error code. If successful, the number of tracks on the CD is returned. + + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_NOCDThere's no CD in the drive. + + + + + + + Retrieves the length (in bytes) of a track. + + The drive... 0 = the first drive. + The track to retrieve the length of... 0 = the first track. + If an error occurs, -1 is returned, use to get the error code. If successful, the length of the track is returned. + CD audio is always 44100hz stereo 16-bit. That's 176400 bytes per second. So dividing the track length by 176400 gives the length in seconds. + See also: and . + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_NOCDThere's no CD in the drive. + BASS_ERROR_CDTRACKThe number is invalid. + BASS_ERROR_NOTAUDIOThe track is not an audio track. + + + + + + + Retrieves the length (in seconds) of a track. + + The drive... 0 = the first drive. + The track to retrieve the length of... 0 = the first track. + If an error occurs, -1 is returned, use to get the error code. If successful, the length of the track in seconds is returned. + CD audio is always 44100hz stereo 16-bit. That's 176400 bytes per second. + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_NOCDThere's no CD in the drive. + BASS_ERROR_CDTRACKThe number is invalid. + BASS_ERROR_NOTAUDIOThe track is not an audio track. + + + + + + + Retrieves the pregap length (in bytes) of a track. + + The drive... 0 = the first drive. + The track to retrieve the pregap length of... 0 = the first track. + If an error occurs, -1 is returned, use to get the error code. + If successful, the pregap length of the track is returned. To translate the pregap length from bytes to frames, divide by 2352. + The drive needs to support sub-channel reading in order to detect all but the first pregap length. + The rwflags member of the structure can be used to check whether the drive can read sub-channel data. + A track's pregap is actually played as part of the preceeding track. + So to remove the gap from the end of a track, you would get the pregap length of the following track. + The gap will usually contain silence, but it doesn't have to - it could contain crowd noise in a live recording, for example. + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_NOCDThere's no CD in the drive. + BASS_ERROR_CDTRACKThe number is invalid. + BASS_ERROR_NOTAUDIOThe track is not an audio track. + BASS_ERROR_NOTAVAILReading sub-channel data is not supported by the drive. + + + + + Get the length of track 1 minus the ending gap (pregap of track 2): + + // get first track length + int len = BassCd.BASS_CD_GetTrackLength(0, 0); + // subtract the ending gap + len -= BassCd.BASS_CD_GetTrackPregap(0, 1); + + + ' get first track length + Dim len As Integer = BassCd.BASS_CD_GetTrackLength(0, 0) + ' subtract the ending gap + len -= BassCd.BASS_CD_GetTrackPregap(0, 1) + + + + + + Creates a sample stream from an audio CD track. + + The drive... 0 = the first drive. + The track... 0 = the first track. + Any combination of these flags (see ): + + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag. See Floating-point channels for more info. + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_LOOPLoop the file. This flag can be toggled at any time using . + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_AUTOFREEAutomatically free the stream's resources when it has reached the end, or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + BASS_CD_SUBCHANNELRead sub-channel data. 96 bytes of de-interleaved sub-channel data will be returned after each 2352 bytes of audio. This flag can not be used with the BASS_SAMPLE_FLOAT flag, and is ignored if the BASS_STREAM_DECODE flag is not used. + BASS_CD_SUBCHANNEL_NOHWRead sub-channel data, without using any hardware de-interleaving. This is identical to the BASS_CD_SUBCHANNEL flag, except that the de-interleaving is always performed by BASSCD even if the drive is apparently capable of de-interleaving itself. + BASS_CD_C2ERRORSInclude C2 error info. 296 bytes of C2 error info is inserted after each 2352 bytes of audio (and optionally 96 bytes of sub-channel data). The first 294 bytes contain the C2 error bits (one bit for each byte of audio), followed by a byte containing the logical "OR" of all 294 bytes, which can be used to quickly check if there were any C2 errors. The final byte is just padding. This flag cannot be used without the BASS_STREAM_DECODE flag or with the BASS_SAMPLE_FLOAT flag; see . + + + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + Only one stream can exist at a time per CD drive. If a stream using the drive already exists, this function will fail, unless the BASS_CONFIG_CD_FREEOLD config option is enabled (see ). + Note that can be used to change track without creating a new stream. + The sample format of a CD audio stream is always 44100hz stereo 16-bit, unless the BASS_SAMPLE_FLOAT flag is used, in which case it's converted to 32-bit. When reading sub-channel data, the sample rate will be 45900hz, taking the additional sub-channel data into account. + When reading sub-channel data, BASSCD will automatically de-interleave the data if the drive can't. You can check whether the drive can de-interleave the data itself (or even read sub-channel data at all) in the the rwflags member of . + When using the BASS_STREAM_DECODE flag, it's not possible to play the stream, but seeking is still possible. Because the decoded sample data is not outputted, "decoding channels" can still be used when there is no output device (using the "no sound" device with ). + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_ALREADYA stream using this drive already exists. + BASS_ERROR_ILLPARAMThe BASS_CD_SUBCHANNEL and BASS_CD_C2ERRORS flags cannot be used without the BASS_STREAM_DECODE flag or with the BASS_SAMPLE_FLOAT flag. See . + BASS_ERROR_NOCDThere's no CD in the drive. + BASS_ERROR_CDTRACK is invalid. + BASS_ERROR_NOTAUDIOThe track is not an audio track. + BASS_ERROR_NOTAVAILReading sub-channel data and/or C2 error info is not supported by the drive, or a read offset is in effect. In case of the latter, see . + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If using the BASS_SAMPLE_FLOAT flag, it could be that floating-point channels are not supported (ie. no WDM drivers). + BASS_ERROR_SPEAKERThe device/drivers do not support the requested speaker(s), or you're attempting to assign a stereo stream to a mono speaker. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Play an entire CD without any gap between tracks: + + private SYNCPROC _mySync; // make it global, so that the GC can not collect it + ... + // create CD stream + int stream = BassCd.BASS_CD_StreamCreate(0, track, BASSFlag.BASS_DEFAULT | BASS_STREAM_AUTOFREE); + _mySync = new SYNCPROC(EndSync); + Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_END | BASSSync.BASS_SYNC_MIXTIME, 0, _mySync, IntPtr.Zero); + // start playing + Bass.BASS_ChannelPlay(stream, false); + ... + private void EndSync(int handle, int channel, int data, IntPtr user) + { + // get current track + int track = Utils.LowWord32(BassCd.BASS_CD_StreamGetTrack(channel)); + // jump to next track + BassCd.BASS_CD_StreamSetTrack(channel, track + 1); + } + + + Private _mySync As SYNCPROC ' make it global, so that the GC can not collect it + ... + ' create CD stream + Dim stream As Integer = BassCd.BASS_CD_StreamCreate(0, track, BASSFlag.BASS_DEFAULT Or BASS_STREAM_AUTOFREE) + _mySync = New SYNCPROC(AddressOf EndSync) + Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_END Or BASSSync.BASS_SYNC_MIXTIME, 0, _mySync, IntPtr.Zero) + ' start playing + Bass.BASS_ChannelPlay(stream, False) + ... + Private Sub EndSync(handle As Integer, channel As Integer, data As Integer, user As IntPtr) + ' get current track + Dim track As Integer = Utils.LowWord32(BassCd.BASS_CD_StreamGetTrack(channel)) + ' jump to next track + BassCd.BASS_CD_StreamSetTrack(channel, track + 1) + End Sub + + + + + + Creates a sample stream from an audio CD track, optionally providing a callback function to receive sub-channel data and/or C2 error info. + + The drive... 0 = the first drive. + The track... 0 = the first track. + Any combination of these flags (see ): + + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag. See Floating-point channels for more info. + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_LOOPLoop the file. This flag can be toggled at any time using . + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_AUTOFREEAutomatically free the stream's resources when it has reached the end, or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + BASS_CD_SUBCHANNELRead sub-channel data. 96 bytes of de-interleaved sub-channel data will be returned after each 2352 bytes of audio. This flag can not be used with the BASS_SAMPLE_FLOAT flag, and is ignored if the BASS_STREAM_DECODE flag is not used. + BASS_CD_SUBCHANNEL_NOHWRead sub-channel data, without using any hardware de-interleaving. This is identical to the BASS_CD_SUBCHANNEL flag, except that the de-interleaving is always performed by BASSCD even if the drive is apparently capable of de-interleaving itself. + BASS_CD_C2ERRORSInclude C2 error info. 296 bytes of C2 error info is inserted after each 2352 bytes of audio data (and optionally 96 bytes of sub-channel data) or delivered to the provided . The first 294 bytes contain the C2 error bits (one bit for each byte of audio), followed by a byte containing the logical "OR" of all 294 bytes, which can be used to quickly check if there were any C2 errors. The final byte is just padding. This flag cannot be used without the BASS_STREAM_DECODE flag or with the BASS_SAMPLE_FLOAT flag, unless a is provided to receive the C2 error info. + + + A callback function to receive sub-channel data and C2 error info... = no callback. If a callback function is provided, sub-channel data and C2 error info will be delivered to it rather than being inserted amongst the sample data. + User instance data to pass to the callback function. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + This function is identical to , but with the additional option of providing a callback function to receive sub-channel data and C2 error info. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_ALREADYA stream using this drive already exists. + BASS_ERROR_ILLPARAMThe BASS_CD_SUBCHANNEL and BASS_CD_C2ERRORS flags cannot be used without the BASS_STREAM_DECODE flag or with the BASS_SAMPLE_FLOAT flag, unless a is provided. + BASS_ERROR_NOCDThere's no CD in the drive. + BASS_ERROR_CDTRACK is invalid. + BASS_ERROR_NOTAUDIOThe track is not an audio track. + BASS_ERROR_NOTAVAILReading sub-channel data and/or C2 error info is not supported by the drive, or a read offset is in effect, in which case a must be provided to receive sub-channel data or C2 error info. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If using the BASS_SAMPLE_FLOAT flag, it could be that floating-point channels are not supported (ie. no WDM drivers). + BASS_ERROR_SPEAKERThe device/drivers do not support the requested speaker(s), or you're attempting to assign a stereo stream to a mono speaker. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + + + + + + + + + Creates a sample stream from an audio CD track, using a CDA file on the CD. + This overload implements Unicode filenames. The BASS_UNICODE flag will be added automatically, if not set. + + The CDA filename... for example, "D:\Track01.cda". + Any combination of these flags: see : + + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag. See Floating-point channels for more info. + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_LOOPLoop the file. This flag can be toggled at any time using . + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_AUTOFREEAutomatically free the stream's resources when it has reached the end, or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + BASS_CD_SUBCHANNELRead sub-channel data. 96 bytes of de-interleaved sub-channel data will be returned after each 2352 bytes of audio. This flag can not be used with the BASS_SAMPLE_FLOAT flag, and is ignored if the BASS_STREAM_DECODE flag is not used. + BASS_CD_SUBCHANNEL_NOHWRead sub-channel data, without using any hardware de-interleaving. This is identical to the BASS_CD_SUBCHANNEL flag, except that the de-interleaving is always performed by BASSCD even if the drive is apparently capable of de-interleaving itself. + BASS_CD_C2ERRORSInclude C2 error info. 296 bytes of C2 error info is inserted after each 2352 bytes of audio (and optionally 96 bytes of sub-channel data). The first 294 bytes contain the C2 error bits (one bit for each byte of audio), followed by a byte containing the logical "OR" of all 294 bytes, which can be used to quickly check if there were any C2 errors. The final byte is just padding. This flag cannot be used without the BASS_STREAM_DECODE flag or with the BASS_SAMPLE_FLOAT flag; see . + BASS_UNICODEfile is a Unicode (16-bit characters) filename (not needed with this overload). + + + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + Only one stream can exist at a time per CD drive. If a stream using the drive already exists, this function will fail, unless the BASS_CONFIG_CD_FREEOLD config option is enabled (see ). + Note that can be used to change track without creating a new stream. + The sample format of a CD audio stream is always 44100hz stereo 16-bit, unless the BASS_SAMPLE_FLOAT flag is used, in which case it's converted to 32-bit. When reading sub-channel data, the sample rate will be 45900hz, taking the additional sub-channel data into account. + When reading sub-channel data, BASSCD will automatically de-interleave the data if the drive can't. You can check whether the drive can de-interleave the data itself (or even read sub-channel data at all) in the the rwflags member of . + When using the BASS_STREAM_DECODE flag, it's not possible to play the stream, but seeking is still possible. Because the decoded sample data is not outputted, "decoding channels" can still be used when there is no output device (using the "no sound" device with ). + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file was not recognised as a CDA file. + BASS_ERROR_ALREADYA stream using this drive already exists. + BASS_ERROR_ILLPARAMThe BASS_CD_SUBCHANNEL and BASS_CD_C2ERRORS flags cannot be used without the BASS_STREAM_DECODE flag or with the BASS_SAMPLE_FLOAT flag. See . + BASS_ERROR_NOTAVAILReading sub-channel data and/or C2 error info is not supported by the drive, or a read offset is in effect. In case of the latter, see . + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If using the BASS_SAMPLE_FLOAT flag, it could be that floating-point channels are not supported (ie. no WDM drivers). + BASS_ERROR_SPEAKERThe device/drivers do not support the requested speaker(s), or you're attempting to assign a stereo stream to a mono speaker. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + + + + + + + + + + + Creates a sample stream from an audio CD track, using a CDA file on the CD, optionally providing a callback function to receive sub-channel data and/or C2 error info. + This overload implements Unicode filenames. The BASS_UNICODE flag will be added automatically, if not set. + + The CDA filename... for example, "D:\Track01.cda". + Any combination of these flags: see : + + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag. See Floating-point channels for more info. + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_LOOPLoop the file. This flag can be toggled at any time using . + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_AUTOFREEAutomatically free the stream's resources when it has reached the end, or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + BASS_CD_SUBCHANNELRead sub-channel data. 96 bytes of de-interleaved sub-channel data will be returned after each 2352 bytes of audio. This flag can not be used with the BASS_SAMPLE_FLOAT flag, and is ignored if the BASS_STREAM_DECODE flag is not used. + BASS_CD_SUBCHANNEL_NOHWRead sub-channel data, without using any hardware de-interleaving. This is identical to the BASS_CD_SUBCHANNEL flag, except that the de-interleaving is always performed by BASSCD even if the drive is apparently capable of de-interleaving itself. + BASS_CD_C2ERRORSInclude C2 error info. 296 bytes of C2 error info is inserted after each 2352 bytes of audio data (and optionally 96 bytes of sub-channel data) or delivered to the provided . The first 294 bytes contain the C2 error bits (one bit for each byte of audio), followed by a byte containing the logical "OR" of all 294 bytes, which can be used to quickly check if there were any C2 errors. The final byte is just padding. This flag cannot be used without the BASS_STREAM_DECODE flag or with the BASS_SAMPLE_FLOAT flag, unless a is provided to receive the C2 error info. + BASS_UNICODEfile is a Unicode (16-bit characters) filename (not needed with this overload). + + + A callback function to receive sub-channel data and C2 error info... = no callback. If a callback function is provided, sub-channel data and C2 error info will be delivered to it rather than being inserted amongst the sample data. + User instance data to pass to the callback function. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + This function is identical to , but with the additional option of providing a callback function to receive sub-channel data and C2 error info. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file was not recognised as a CDA file. + BASS_ERROR_ALREADYA stream using this drive already exists. + BASS_ERROR_ILLPARAMThe BASS_CD_SUBCHANNEL and BASS_CD_C2ERRORS flags cannot be used without the BASS_STREAM_DECODE flag or with the BASS_SAMPLE_FLOAT flag, unless a is provided. + BASS_ERROR_NOTAVAILReading sub-channel data and/or C2 error info is not supported by the drive, or a read offset is in effect, in which case a must be provided to receive sub-channel data or C2 error info. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If using the BASS_SAMPLE_FLOAT flag, it could be that floating-point channels are not supported (ie. no WDM drivers). + BASS_ERROR_SPEAKERThe device/drivers do not support the requested speaker(s), or you're attempting to assign a stereo stream to a mono speaker. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Retrieves the drive and track number of a CD stream. + + The CD stream handle. + If an error occurs, -1 is returned, use to get the error code. + If successful, the track number is returned in the low word (low 16-bits), and the drive is returned in the high word (high 16-bits). + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + Check if a channel is a CD stream, and then get it's drive and track number. + + int track = BassCd.BASS_CD_StreamGetTrack(channel); + if (track != -1) + { + int drive = Utils.HighWord32(track); + track = Utils.LowWord32(track); + } + + + Dim track As Integer = BassCd.BASS_CD_StreamGetTrack(channel) + If track <> - 1 Then + Dim drive As Integer = Utils.HighWord32(track) + track = Utils.LowWord32(track) + End If + + + + + + Changes the track of a CD stream. + + The CD stream handle. + The new track... 0 = the first track. + If successful, is returned, else is returned. Use to get the error code. + The stream's current position is set to the start of the new track. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOCDThere's no CD in the drive. + BASS_ERROR_CDTRACK is invalid. + BASS_ERROR_NOTAUDIOThe track is not an audio track. + + + + + Play an entire CD without any gap between tracks: + + private SYNCPROC _mySync; // make it global, so that the GC can not collect it + ... + // create CD stream + int stream = BassCd.BASS_CD_StreamCreate(0, track, BASSFlag.BASS_DEFAULT | BASS_STREAM_AUTOFREE); + _mySync = new SYNCPROC(EndSync); + Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_END | BASSSync.BASS_SYNC_MIXTIME, 0, _mySync, IntPtr.Zero); + // start playing + Bass.BASS_ChannelPlay(stream, false); + ... + private void EndSync(int handle, int channel, int data, IntPtr user) + { + // get current track + int track = Utils.LowWord32(BassCd.BASS_CD_StreamGetTrack(channel)); + // jump to next track + BassCd.BASS_CD_StreamSetTrack(channel, track + 1); + } + + + Private _mySync As SYNCPROC ' make it global, so that the GC can not collect it + ... + ' create CD stream + Dim stream As Integer = BassCd.BASS_CD_StreamCreate(0, track, BASSFlag.BASS_DEFAULT Or BASS_STREAM_AUTOFREE) + _mySync = New SYNCPROC(AddressOf EndSync) + Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_END Or BASSSync.BASS_SYNC_MIXTIME, 0, _mySync, IntPtr.Zero) + ' start playing + Bass.BASS_ChannelPlay(stream, False) + ... + Private Sub EndSync(handle As Integer, channel As Integer, data As Integer, user As IntPtr) + ' get current track + Dim track As Integer = Utils.LowWord32(BassCd.BASS_CD_StreamGetTrack(channel)) + ' jump to next track + BassCd.BASS_CD_StreamSetTrack(channel, track + 1) + End Sub + + + + + + Starts analog playback of an audio CD track. + + The drive... 0 = the first drive. + The track... 0 = the first track. + Position (in frames) to start playback from. There are 75 frames per second. + If successful, is returned, else is returned. Use to get the error code. + + Some old CD drives may not be able to digitally extract audio data (or not quickly enough to sustain playback), so that it's not possible to use to stream CD tracks. + This is where the analog playback option can come in handy. + In analog playback, the sound bypasses BASS - it goes directly from the CD drive to the soundcard (assuming the drive is cabled up to the soundcard). + This means that BASS output does not need to be initialized to use analog playback. It also means it's not possible to apply any DSP/FX to the sound, and nor is it possible to visualise it (unless you record the sound from the soundcard). + Analog playback is not possible while digital streaming is in progress - the streaming will kill the analog playback. So if you wish to switch from digital to analog playback, you should first free the stream using . + + + ERROR CODEDescription + BASS_ERROR_DEVICE is not valid. + BASS_ERROR_NOCDThere's no CD in the drive. + BASS_ERROR_CDTRACK is invalid. + BASS_ERROR_NOTAUDIOThe track is not an audio track. + BASS_ERROR_POSITION is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Play track 3 on drive 0, starting at the 10 second point: + + bool ok = BassCd.BASS_CD_Analog_Play(0, 3, 10 * 75); + + + Dim ok As Boolean = BassCd.BASS_CD_Analog_Play(0, 3, 10 * 75) + + + + + + Starts analog playback of an audio CD track. + + The drive... 0 = the first drive. + The track... 0 = the first track. + Position (in seconds) to start playback from (this will automatically be converted to frames internally). + If successful, is returned, else is returned. Use to get the error code. + + Some old CD drives may not be able to digitally extract audio data (or not quickly enough to sustain playback), so that it's not possible to use to stream CD tracks. + This is where the analog playback option can come in handy. + In analog playback, the sound bypasses BASS - it goes directly from the CD drive to the soundcard (assuming the drive is cabled up to the soundcard). + This means that BASS output does not need to be initialized to use analog playback. It also means it's not possible to apply any DSP/FX to the sound, and nor is it possible to visualise it (unless you record the sound from the soundcard). + Analog playback is not possible while digital streaming is in progress - the streaming will kill the analog playback. So if you wish to switch from digital to analog playback, you should first free the stream using . + + + ERROR CODEDescription + BASS_ERROR_DEVICE is not valid. + BASS_ERROR_NOCDThere's no CD in the drive. + BASS_ERROR_CDTRACK is invalid. + BASS_ERROR_NOTAUDIOThe track is not an audio track. + BASS_ERROR_POSITION is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Play track 3 on drive 0, starting at the 10 second point: + + bool ok = BassCd.BASS_CD_Analog_Play(0, 3, 10.0); + + + Dim ok As Boolean = BassCd.BASS_CD_Analog_Play(0, 3, 10.0) + + + + + + Starts analog playback of an audio CD track, using a CDA file on the CD. + + The CDA filename... for example, "D:\Track01.cda". + Position (in frames) to start playback from. There are 75 frames per second. + If successful, the number of the drive being used is returned, else -1 is returned. Use to get the error code. + + Some old CD drives may not be able to digitally extract audio data (or not quickly enough to sustain playback), so that it's not possible to use to stream CD tracks. + This is where the analog playback option can come in handy. + In analog playback, the sound bypasses BASS - it goes directly from the CD drive to the soundcard (assuming the drive is cabled up to the soundcard). + This means that BASS output does not need to be initialized to use analog playback. It also means it's not possible to apply any DSP/FX to the sound, and nor is it possible to visualise it (unless you record the sound from the soundcard). + Analog playback is not possible while digital streaming is in progress - the streaming will kill the analog playback. So if you wish to switch from digital to analog playback, you should first free the stream using . + + + ERROR CODEDescription + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file was not recognised as a CDA file. + BASS_ERROR_DEVICEThe drive could not be found. + BASS_ERROR_POSITION is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Play track 3 on drive D:, starting at the 10 second point: + + int drive = BassCd.BASS_CD_Analog_PlayFile("D:\\Track03.cda", 10 * 75); + + + Dim drive As Integer = BassCd.BASS_CD_Analog_PlayFile("D:\Track03.cda", 10 * 75) + + + + + + Starts analog playback of an audio CD track, using a CDA file on the CD. + + The CDA filename... for example, "D:\Track01.cda". + Position (in seconds) to start playback from (automatically converted to frames internally). + If successful, the number of the drive being used is returned, else -1 is returned. Use to get the error code. + + Some old CD drives may not be able to digitally extract audio data (or not quickly enough to sustain playback), so that it's not possible to use to stream CD tracks. + This is where the analog playback option can come in handy. + In analog playback, the sound bypasses BASS - it goes directly from the CD drive to the soundcard (assuming the drive is cabled up to the soundcard). + This means that BASS output does not need to be initialized to use analog playback. It also means it's not possible to apply any DSP/FX to the sound, and nor is it possible to visualise it (unless you record the sound from the soundcard). + Analog playback is not possible while digital streaming is in progress - the streaming will kill the analog playback. So if you wish to switch from digital to analog playback, you should first free the stream using . + + + ERROR CODEDescription + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file was not recognised as a CDA file. + BASS_ERROR_DEVICEThe drive could not be found. + BASS_ERROR_POSITION is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Play track 3 on drive D:, starting at the 10 second point: + + int drive = BassCd.BASS_CD_Analog_PlayFile("D:\Track03.cda", 10.0); + + + Dim drive As Integer = BassCd.BASS_CD_Analog_PlayFile("D:\Track03.cda", 10.0) + + + + + + Stops analog playback on a drive. + + The drive... 0 = the first drive. + If successful, is returned, else is returned. Use to get the error code. + Pausing can be achieved by getting the position () just before stopping, and then using that position in a call to to resume. + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Checks if analog playback is in progress on a drive. + + The drive... 0 = the first drive. + The return value is one of the folowing (see ): + + BASS_ACTIVE_STOPPEDAnalog playback is not in progress, or is invalid. + BASS_ACTIVE_PLAYINGAnalog playback is in progress. + + + + + + Retrieves the current position and track on a drive. + + The drive... 0 = the first drive. + If an error occurs, -1 is returned, use to get the error code. + If successful, the HIWORD contains the track number (0=first), and the LOWORD contains the offset (in frames). + + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + // get the position + int pos = BassCd.BASS_CD_Analog_GetPosition(0); + int track = Utils.HighWord32(pos); + int frame = Utils.LowWord32(pos); + double sec = frame / 75.0; + + + ' get the position + Dim pos As Integer = BassCd.BASS_CD_Analog_GetPosition(0) + Dim track As Integer = Utils.HighWord32(pos) + Dim frame As Integer = Utils.LowWord32(pos) + Dim sec As Double = frame / 75.0 + + + + + + Retrieves the current position on a drive in seconds. + + The drive... 0 = the first drive. + Returns the current track number being played. + If an error occurs, -1 is returned, use to get the error code. + If successful, the position in seconds is returned. + + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + int track = 0; + double sec = BASS_CD_Analog_GetPosition(0, ref track); + + + Dim track As Integer = 0 + Dim sec As Double = BASS_CD_Analog_GetPosition(0, track) + + + + + + Supported file extensions of the basscd.dll + + + + + Supported file format name of the basscd.dll + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + The disadvantage of this method is, that the standard plugin support for is not working - so you would need to use the native add-on methods! + + + Load BASS and BASSCD from the application's startup path: + + Bass.LoadMe(); + BassCd.LoadMe(); + ... + // when not used anymore... + BassCd.FreeMe(); + Bass.FreeMe(); + + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + Load BASS and BASSCD from a different directory: + + Bass.LoadMe( @"C:\Development\BASS\_libs" ); + BassCd.LoadMe( @"C:\Development\BASS\_libs" ); + ... + // when not used anymore... + BassCd.FreeMe(); + Bass.FreeMe(); + + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + The interface to use to access CD drives (used with ). + + + + + Automatically detect an available interface. The interfaces are checked in the order that they are listed here. For example, if both SPTI and ASPI are available, SPTI will be used. + + + + + SCSI Pass-Through Interface. This is only available on NT-based Windows, not Windows 9x, and generally only to administrator user accounts, not limited/restricted user accounts. + + + + + Advanced SCSI Programming Interface. This is the only interface available on Windows 9x, and can also be installed on NT-based Windows. + + + + + Windows I/O. Like SPTI, this is only available on NT-based Windows, but it is also available to limited/restricted user accounts. Some features are not available via this interface, notably sub-channel data reading and read speed control (except on Vista or newer). Door status detection is also affected. + + + + + The drive's reading & writing capabilities used with . + + + + + The drive can read CD-R media. + + + + + The drive can read CD-RW media. + + + + + The drive can read CD-R/RW media where the addressing type is "method 2". + + + + + The drive can read DVD-ROM media. + + + + + The drive can read DVD-R media. + + + + + The drive can read DVD-RAM media. + + + + + The drive is capable of analog playback. + + + + + The drive can read in "mode 2 form 1" format. + + + + + The drive can read in "mode 2 form 2" format. + + + + + The drive can read multi-session discs. + + + + + The drive can read CD audio. + + + + + The drive supports "stream is accurate". + + + + + The drive can read sub-channel data. + + + + + The drive can read sub-channel data, and de-interleave it. + + + + + The drive can provide C2 error info. + + + + + The drive can read ISRC numbers. + + + + + The drive can read UPC numbers. + + + + + The BASS_CD_Door actions to perform, used with . + + + + + Close the door. + + + + + Open the door. + + + + + Lock the door. + + + + + Unlock the door. + + + + + The identification to retrieve, used with . + + + + + Returns the catalog number of the CD. The number uses UPC/EAN-code (BAR coding). This might not be available for all CDs. + + + + + Produces a CDDB identifier. This can be used to get details on the CD's contents from a CDDB server. + + + + + Produces a CDDB2 identifier. This can be used to get details on the CD's contents from a CDDB2 server. + + + + + Retrieves the CD-TEXT information from the CD (see for details). CD-TEXT is not available on the majority of CDs. + + + + + Produces an identifier that can be used to lookup CD details in the CDPLAYER.INI file, located in the Windows directory. + + + + + Produces an identifier that can be used to get details on the CD's contents from www.musicbrainz.org. + + + + + Use: + track#. Returns the International Standard Recording Code of the track... 0 = first track. This might not be available for all CDs. + + + + + Sends a "query" command to the configured CDDB server (see ) to get a list of matching entries for the CD's CDDB identifier. The contents of each entry can be retrieved via the BASS_CDID_CDDB_READ option. + + + + + Use: + entry#. Sends a "read" command to the configured CDDB server (see ) to get a database entry for the CD's CDDB identifier... 0 = first entry. + + + + + Returns the cached CDDB "read" command response, if there is one. + + + + + The type of data received, used with . + + + + + Sub-channel data. + + + + + C2 error info. + + + + + The mode to use with . + + + + + Get the track start address in LBA form. + + + + + Get the track start address in time form (hour, minute, second, frame). + + + + + + track#, Get the position of indexes (instead of tracks) + When this option is used, the 'first' and 'last' members of the structure are index numbers, + and the 'track' member of the BASS_CD_TOC_TRACK structure is also an index number and the "lba" or "hmsf" member (depending on whether BASS_CD_TOC_TIME is used) is an offset from the start of the track + + + + + The "adrcon" flags. + + + + + No flag defined. + + + + + Pre-emphasis of 50/15 µs. + + + + + Digital copy permitted. + + + + + Data track. + + + + + Used with to retrieve information on a drive. + + The rwflags, maxspeed and cache members are unavailable when the WIO interface is used. + + + + The drive manufacturer name. + + + + + The drive product/model name. + + + + + The revision number as a string. + + + + + The drive letter... -1=unknown, 0=A, 1=B, etc. + + + + + Read/Write capability flags (any combination of ). + + + + + If , can be used and BASS_CD_DOOR_OPEN/CLOSE is supported? + + + + + If , can be used and BASS_CD_DOOR_LOCK/UNLOCK is supported? + + + + + The maximum read speed, in kilobytes per second (KB/s). Divide by 176.4 to get the real-time speed multiplier, eg. 5645 / 176.4 = "32x speed". + + + + + The drive's cache size, in kilobytes (KB). + + + + + The drive can read CD-TEXT? + + + + + Default constructor. + + + + + A description of the decive info object (driver name, version, number of inputs/outputs). + + A description of the decive info object (driver name, version, number of inputs/outputs). + + + + Gets the character letter of the drive. + + Only available after has been called with this instance. + + + + Used with to retrieve the TOC from a CD. + + + + + The byte length of the TOC data, not including the 2 bytes taken by this size member. + + + + + The first track number (or index number if BASS_CD_TOC_INDEX is used). + + + + + The last track number (or index number if BASS_CD_TOC_INDEX is used). + + + + + The array of tracks (up to 100 tracks). + + Note: Use the property to determine the effective number of tracks retrieved. + + + + Gets the effective number of tracks retrieved. + + + + + Used with to retrieve the TOC from a CD. + + + + + The first track number (or index number if BASS_CD_TOC_INDEX is used). + + + + + The last track number (or index number if BASS_CD_TOC_INDEX is used). + + + + + The list of tracks retrieved (see , up to 100 tracks). + + + + + A description of the TOC info object (number of tracks, first, last). + + A description of the TOC info object (number of tracks, first, last). + + + + Represents one track of a CD's TOC (see ). + + + + + Unused. + + + + + ADR (high 4 bits) and control (low 4 bits) fields. + + The control field indicates the attributes of the track, and may include the following (see ): + + AttributeDescription + BASS_CD_TOC_CON_COPYDigital copy permitted. + BASS_CD_TOC_CON_DATAData track. + BASS_CD_TOC_CON_PREPre-emphasis of 50/15 µs. + + You might use the and properties to get the respective fields directly. + + + + + The track number... 170 = lead-out area (or index number if BASS_CD_TOC_INDEX is used). + + + + + Unused. + + + + + The address in LBA (Logical Block Address) form. + + + Only to be used, if the or flag was used in the call. + With the BASS_CD_TOC_INDEX flag this is an offset from the start of the track. + + + + + A description of the TOC_TRACK info object (track, adr, con, start address in lba and time). + + A description of the TOC_TRACK info object (track, adr, con, start address in lba and time). + + + + The address in time form (hour part). + + Only to be used, if the flag was used in the call. + The hours field is always 0, and the minutes field will be above 60 instead if necessary. + + + + + The address in time form (minute part). + + Only to be used, if the flag was used in the call. + The hours field is always 0, and the minutes field will be above 60 instead if necessary. + + + + + The address in time form (second part). + + Only to be used, if the flag was used in the call. + + + + + The address in time form (frame part). + + Only to be used, if the flag was used in the call. + + + + + Gets the ADR component of the field. + + + + + Gets the control component of the field. + + The control field indicates the attributes of the track, and may include the following (see ): + + AttributeDescription + BASS_CD_TOC_CON_COPYDigital copy permitted. + BASS_CD_TOC_CON_DATAData track. + BASS_CD_TOC_CON_PREPre-emphasis of 50/15 µs. + + + + + + User defined CD data callback delegate (to be used with or ). + + The CD stream that provided the data. + The stream position (in bytes) that the data is from. + The type of data, which can be one of the following (see ): + BASS_CD_DATA_SUBCHANNEL : Sub-channel data. + BASS_CD_DATA_C2 : C2 error info. + + The pointer to the buffer data. + The amount of data in bytes. + The user instance data given when or was called. + + Sub-channel data or C2 error info is delivered to this function as soon as it is read from the CD, before the associated audio data is played, or delivered by in the case of a decoding channel. + The pos value can be used to synchronize the delivered data with the stream's audio data. + CDs are read from in units of a frame, and so this function will always receive a whole number of frames' worth of data; there are 96 bytes of sub-channel data per-frame, and 296 bytes of C2 error info. + When has been used to set a read offset, playback may begin mid-frame, and as a result of that, may start out negative because the delivered data is from the start of the 1st frame, before where playback will begin from. + Neither sub-channel data or C2 error info will be delivered in the case of a silenced frame resulting from the config option being enabled. + + + + + This class represents the general Win32 MIDI Functions and Constants. + Requires: winmm.dll - Microsoft Multimedia Win32 library. + + The Musical Instrument Digital Interface (MIDI) is a protocol and set of commands for storing and transmitting information about music or devices. MIDI output devices for example might interpret this information and use it to synthesize music. + Querying MIDI Devices: + Before playing or recording MIDI data, you must determine the capabilities of the MIDI hardware present in the system. MIDI capability can vary from one multimedia computer to the next. Applications should not make assumptions about the hardware present in a given system. + The following functions are provided to determine how many MIDI devices are available for input or output in a given system: , , and . + Like other audio devices, MIDI devices are identified by a device identifier, which is determined implicitly from the number of devices present in a given system. Device identifiers range from zero to the number of devices present, minus one. For example, if there are two MIDI output devices in a system, valid device identifiers are 0 and 1. + After you determine how many MIDI input or output devices are present in a system, you can inquire about the capabilities of each device. Windows provides the following functions to determine the capabilities of audio devices. + + Opening and Closing Device Drivers: + You must open a MIDI device before using it, and you should close the device as soon as you finish using it. The following functions are provided to open and close different types of MIDI devices: , , and . + Each function that opens a MIDI device takes as parameters a device identifier, an address of a memory location, and some parameters unique to MIDI devices. The memory location is filled with a device handle, which is used to identify the open audio device in calls to other audio functions. + Many MIDI functions can accept either a device handle or a device identifier. Although you can use a device handle wherever you would use a device identifier, you cannot always use a device identifier when a handle is called for. + Note: MIDI devices are not necessarily shareable, so a particular device may not be available when a user requests it. If this happens, the application should notify the user and allow the user to try to open the device again. + + Allocating and Preparing MIDI Data Blocks: + The and functions require that applications to allocate data blocks to pass to the device drivers for playback or recording purposes. Each of these functions uses a structure to describe its data block. + Before you use one of these functions to pass a data block to a device driver, you must allocate memory for the buffer and the header structure that describes the data block. + The following functions are provided for preparing and cleaning up MIDI data blocks: , , and . + Before you pass a MIDI data block to a device driver, you must prepare the buffer by passing it to the or function. When the device driver is finished with the buffer and returns it, you must clean up this preparation by passing the buffer to the or function before any allocated memory can be freed. + + Managing MIDI Data Blocks: + Applications that use data blocks for passing system-exclusive messages (using the and functions) and stream buffers must continually supply the device driver with data blocks until playback or recording is complete. + Even if a single data block is used, an application must be able to determine when a device driver is finished with the data block so it can free the memory associated with the data block and header structure. Three methods can be used to determine when a device driver is finished with a data block: + + Specify a callback function to receive a message sent by the driver when it is finished with a data block. To get time-stamped MIDI input data, you must use a callback function. + Use an event callback (for output only). + Use a window or thread callback to receive a message sent by the driver when it is finished with a data block. Note: This is not recommended in a .Net environment! + + If an application does not get a data block to the device driver when it is needed, an audible gap in playback or a loss of incoming recorded information can occur. At a minimum, an application should use a double-buffering scheme to stay at least one data block ahead of the device driver. + + You can write your own callback function to process messages sent by the device driver. To use a callback function, specify the flag in the flags parameter and the address of the callback function in the proc parameter of the or function. + Sending System-Exclusive Messages: + MIDI system-exclusive messages are the only MIDI messages that will not fit into a single Int32 value. System-exclusive messages can be any length. The function is provided for sending system-exclusive messages to MIDI output devices. + To specify MIDI system-exclusive data blocks, use the structure. + After you send a system-exclusive data block using , you must wait until the device driver is finished with the data block before freeing it. If you are sending multiple data blocks, you must monitor the completion of each data block so you know when to send additional blocks. + Note: Any MIDI status byte other than a system-real-time message will terminate a system-exclusive message. If you are using multiple data blocks to send a single system-exclusive message, do not send any MIDI messages other than system-real-time messages between data blocks. + + Managing MIDI Recording: + After you open a MIDI device, you can begin recording MIDI data. The following functions are provided for managing MIDI recording: , , and . + To send buffers to the device driver for recording system-exclusive messages, use . The application is notified as the buffers are filled with system-exclusive recorded data. + The function begins the recording process. When recording system-exclusive messages, send at least one buffer to the driver before starting recording. To stop recording, use . Before closing the device by using the function, mark any pending data blocks as being done by calling . + Applications that require time-stamped data use a callback function to receive MIDI data. + To record system-exclusive messages with applications that do not use stream buffers, you must supply the device driver with buffers. These buffers are specified by using a structure. + + Managing MIDI Thru: + You can connect a MIDI input device directly to a MIDI output device so that when the input device receives an MIM_DATA message, the system sends a message with the same MIDI event data to the output device driver. + To connect a MIDI output device to a MIDI input device, use the function. + To achieve the best possible performance with multiple outputs, an application can choose to supply a special form of MIDI output driver, called a thru driver. Although the system allows only one MIDI output device to be connected to a MIDI input device, multiple MIDI output devices can be connected to a thru driver. + An application on such a system could connect the MIDI input device to this thru device and connect the MIDI thru device to as many MIDI output devices as needed. For more information about thru drivers, see the Windows device-driver documentation. + + Receiving Running-Status Messages: + The Standard MIDI Files 1.0 specification allows the use of running status when a message has the same status byte as the previous message. When running status is used, the status byte of subsequent messages can be omitted. All MIDI input device drivers are required to expand messages using running status into complete messages, so that you always receive complete MIDI messages from a MIDI input device driver. + + Handling Errors with MIDI Functions: + MIDI audio functions return a nonzero error code. For MIDI-associated errors, the functions retrieve textual descriptions for the error codes. The application must still look at the error value itself to determine how to proceed, but it can use the error descriptions in dialog boxes to inform users of the error conditions. + The only MIDI functions that do not return error codes are the and functions. These functions return a value of zero if no devices are present in a system or if any errors are encountered by the function. + + This class does not implement MIDI Streams (see the add-on for real-time playback of MIDI streams)! + + + + + Returns the error message for a given error code. + + Dealing with an input device? =input, =output. + The error code to get the message from. + The error message associated with the error code. + + + + Determines the capabilities of a specified MIDI input device. + + Identifier of the MIDI input device. The device identifier varies from zero to one less than the number of devices present. + An instance of the class that is filled with information about the capabilities of the device. + Returns 0 if successful or an error otherwise. For possible error values see . + To determine the number of MIDI input devices present on the system, use the function. + + List all Midi input devices: + + int count = Midi.MIDI_InGetNumDevs(); + MIDI_INCAPS inCaps = new MIDI_INCAPS(); + for (int i=0; i<count; i++) + { + Midi.MIDI_InGetDevCaps(i, inCaps); + Console.WriteLine( inCaps.name ); + } + + + Dim count As Integer = Midi.MIDI_InGetNumDevs() + Dim inCaps As New MIDI_INCAPS() + Dim i As Integer + For i = 0 To count-1 + Midi.MIDI_InGetDevCaps(i, inCaps) + Console.WriteLine(inCaps.name) + Next i + + + + + + Retrieves the number of MIDI input devices in the system. + + Returns the number of MIDI input devices present in the system. A return value of zero means that there are no devices (not that there is no error). + + List all Misi input devices: + + int count = Midi.MIDI_InGetNumDevs(); + MIDI_INCAPS inCaps = new MIDI_INCAPS(); + for (int i=0; i<count; i++) + { + Midi.MIDI_InGetDevCaps(i, inCaps); + Console.WriteLine( inCaps.name ); + } + + + Dim count As Integer = Midi.MIDI_InGetNumDevs() + Dim inCaps As New MIDI_INCAPS() + Dim i As Integer + For i = 0 To count-1 + Midi.MIDI_InGetDevCaps(i, inCaps) + Console.WriteLine(inCaps.name) + Next i + + + + + + Queries a specified MIDI output device to determine its capabilities. + + Identifier of the MIDI output device. The device identifier varies from zero to one less than the number of devices present. + An instance of the class that is filled with information about the capabilities of the device. + Returns 0 if successful or an error code otherwise. For possible error values see . + To determine the number of MIDI output devices present on the system, use the function. + + List all Midi output port devices: + + int count = Midi.MIDI_OutGetNumDevs(); + MIDI_OUTCAPS outCaps = new MIDI_OUTCAPS(); + for (int i=0; i<count; i++) + { + Midi.MIDI_OutGetDevCaps(i, outCaps); + if (outCaps.IsMidiPort) + Console.WriteLine( outCaps.name ); + } + + + Dim count As Integer = Midi.MIDI_OutGetNumDevs() + Dim outCaps As New MIDI_OUTCAPS() + Dim i As Integer + For i = 0 To count-1 + Midi.MIDI_OutGetDevCaps(i, outCaps) + If outCaps.IsMidiPort Then + Console.WriteLine(outCaps.name) + End If + Next i + + + + + + Retrieves the number of MIDI output devices present in the system. + + Returns the number of MIDI output devices. A return value of zero means that there are no devices (not that there is no error). + + List all Midi output devices: + + int count = Midi.MIDI_OutGetNumDevs(); + MIDI_OUTCAPS outCaps = new MIDI_OUTCAPS(); + for (int i=0; i<count; i++) + { + Midi.MIDI_OutGetDevCaps(i, outCaps); + Console.WriteLine( outCaps.name ); + } + + + Dim count As Integer = Midi.MIDI_OutGetNumDevs() + Dim outCaps As New MIDI_OUTCAPS() + Dim i As Integer + For i = 0 To count-1 + Midi.MIDI_OutGetDevCaps(i, outCaps) + Console.WriteLine(outCaps.name) + Next i + + + + + + Opens a MIDI input device. + + Returns the MIDI input handle. The handle is used to identify the device in calls to other MIDI input functions. + Identifier of the MIDI input device to be opened (see for details). + The callback delegate to use (which will receive all messages). For more information on the callback function, see . + User instance data passed to the callback function. + A combination of the following (see ): + + MIDI_IO_STATUSWhen this parameter is also specified with MIDI_CALLBACK_FUNCTION, then MIM_MOREDATA messages are sent to the callback function as well as MIM_DATA messages. + MIDI_CALLBACK_FUNCTIONThe proc parameter is a callback procedure address. + MIDI_CALLBACK_NULLThere is no callback mechanism (proc must be ). + + + Returns 0 if successful or an error code otherwise. For possible error values see . + + You only need to set the MIDI_IO_STATUS flag if needed, since the other flags are automatically set according to the given . + To determine the number of MIDI input devices present in the system, use the function. The device identifier specified by varies from zero to one less than the number of devices present. + If a function is chosen to receive callback information, the following messages are sent to the function to indicate the progress of MIDI input (see ): MIM_OPEN, MIM_CLOSE, MIM_DATA, MIM_LONGDATA, MIM_ERROR, MIM_LONGERROR, and MIM_MOREDATA. + If you use the MIDI_IO_STATUS flag with this method, the system uses the MIM_MOREDATA message to alert your application's callback function when it is not processing MIDI data fast enough to keep up with the input device driver. + If your application processes MIDI data in a separate thread, boosting the thread's priority can have a significant impact on the application's ability to keep up with the data flow. + + + + private MIDIINPROC _midiProc; + private IntPtr _midiInHandle; + ... + // Open the Midi device #1 + _midiProc = new MIDIINPROC(MyMidiProc); + MIDIError ret = Midi.MIDI_InOpen(ref _midiInHandle, 1, _midiProc, IntPtr.Zero, MIDIFlags.MIDI_IO_STATUS); + if (ret == MIDIError.MIDI_OK) + { + // Start the device + ret = Midi.MIDI_InStart(_midiInHandle); + } + ... + // when not needed anymore...stop the device + Midi.MIDI_InReset(_midiInHandle); + // and close the device + Midi.MIDI_InClose(_midiInHandle); + ... + public void MyMidiProc(IntPtr handle, MIDIMessage msg, IntPtr instance, IntPtr param1, IntPtr param2) + { + // handle all Midi messages here + if (msg == MIDIMessage.MIM_OPEN) + { + // nothing to do + } + else if (msg == MIDIMessage.MIM_CLOSE) + { + // handle is from now on invalid + } + else if (msg == MIDIMessage.MIM_DATA) + { + // process the message... + int p1 = param1.ToInt32(); + int p2 = param2.ToInt32(); + ... + } + else if (msg == MIDIMessage.MIM_MOREDATA) + { + // we are not fast enough in this callback to keep up... + // the input device is sending messages to fast + ... + } + else if (msg == MIDIMessage.MIM_LONGDATA) + { + // process the message... + ... + } + else if (msg == MIDIMessage.MIM_ERROR) + { + // process the invalid message... + ... + } + else if (msg == MIDIMessage.MIM_LONGERROR) + { + // process the invalid message... + ... + } + } + + + Private _midiProc As MIDIINPROC + Private _midiInHandle As IntPtr + ... + ' Open the Midi device #1 + _midiProc = New MIDIINPROC(AddressOf MyMidiProc) + Dim ret As MIDIError = Midi.MIDI_InOpen(_midiInHandle, 1, _midiProc, IntPtr.Zero, MIDIFlags.MIDI_IO_STATUS) + If ret = MIDIError.MIDI_OK Then + ' Start the device + ret = Midi.MIDI_InStart(_midiInHandle) + End If + ... + ' when not needed anymore...stop the device + Midi.MIDI_InReset(_midiInHandle) + ' and close the device + Midi.MIDI_InClose(_midiInHandle) + ... + Public Sub MyMidiProc(handle As IntPtr, msg As MIDIMessage, instance As IntPtr, param1 As IntPtr, param2 As IntPtr) + ' handle all Midi messages here + If msg = MIDIMessage.MIM_OPEN Then + ' nothing to do + Else + If msg = MIDIMessage.MIM_CLOSE Then + ' handle is from now on invalid + Else + If msg = MIDIMessage.MIM_DATA Then + ' process the message... + Dim p1 As Integer = param1.ToInt32() + Dim p2 As Integer = param2.ToInt32() + ... + Else + If msg = MIDIMessage.MIM_MOREDATA Then + ' we are not fast enough in this callback to keep up... + ' the input device is sending messages to fast + ... + Else + If msg = MIDIMessage.MIM_LONGDATA Then + ' process the message... + ... + Else + If msg = MIDIMessage.MIM_ERROR Then + ' process the invalid message... + ... + Else + If msg = MIDIMessage.MIM_LONGERROR Then + ' process the invalid message... + ... + End If + End If + End If + End If + End If + End If + End If + End Sub + + + + + + Closes the specified MIDI input device. + + Handle to the MIDI input device. If the function is successful, the handle is no longer valid after the call to this function. + Returns 0 if successful or an error code otherwise. For possible error values see . + If there are input buffers that have been sent by using the function and have not been returned to the application, the close operation will fail. + To return all pending buffers through the callback function, use the function. + + + + + Opens a MIDI output device for playback. + + Returns the MIDI output handle. The handle is used to identify the device in calls to other MIDI output functions. + Identifier of the MIDI output device to be opened (see for details). + The callback delegate to use. Called during MIDI playback to process messages related to the progress of the playback. If no callback is desired, specify for this parameter. For more information on the callback function, see . + User instance data passed to the callback function. + Returns 0 if successful or an error code otherwise. For possible error values see . + + The flags are automatically set according to the given (thats why this method does not contain any flags parameter). + To determine the number of MIDI output devices present in the system, use the function. The device identifier specified by varies from zero to one less than the number of devices present. + If a function is chosen to receive callback information, the following messages are sent to the function to indicate the progress of MIDI output: MOM_OPEN, MOM_CLOSE, and MOM_DONE. + + + + private MIDIOUTPROC _midiProc; + private IntPtr _midiOutHandle; + ... + // Open the Midi device #2 + _midiProc = new MIDIOUTPROC(MyMidiProc); + MIDIError ret = Midi.MIDI_OutOpen(ref _midiOutHandle, 2, _midiProc, 0); + if (ret == MIDIError.MIDI_OK) + { + // device opened and ready + } + ... + // When not needed anymore...stop the device + Midi.MIDI_OutReset(_midiOutHandle); + // and close the device + Midi.MIDI_OutClose(_midiOutHandle); + ... + private void SendShortMessage(int message) + { + MIDI_OutShortMsg(_midiOutHandle, message); + } + + private void SendSysExMessage(byte[] data) + { + MIDI_HEADER header = new MIDI_HEADER(data); + header.Prepare(false, _midiOutHandle); + // If the header was perpared successfully. + if (header.HeaderPtr != IntPtr.Zero) + { + // send a system-exclusive message to the output device + Midi.MIDI_OutLongMsg(_midiOutHandle, header.HeaderPtr); + } + } + + public void MyMidiProc(IntPtr handle, MIDIMessage msg, IntPtr instance, IntPtr param1, IntPtr param2) + { + // handle all Midi messages here + if (msg == MIDIMessage.MOM_OPEN) + { + // nothing to do + } + else if (msg == MIDIMessage.MOM_CLOSE) + { + // handle is from now on invalid + } + else if (msg == MIDIMessage.MOM_DONE) + { + // process the message... + // param1 will contain the pointer to the MIDI_HEADER + MIDI_HEADER header = new MIDI_HEADER(param1); + // process the header if needed + ... + // and finally unprepare the header + header.Unprepare(false, handle); + } + } + + + Private _midiProc As MIDIOUTPROC + Private _midiOutHandle As IntPtr + ... + ' Open the Midi device #2 + _midiProc = New MIDIOUTPROC(MyMidiProc) + Dim ret As MIDIError = Midi.MIDI_OutOpen(_midiOutHandle, 2, _midiProc, 0) + If ret = MIDIError.MIDI_OK Then + ' device opened and ready + End If + ... + ' when not needed anymore...stop the device + Midi.MIDI_OutReset(_midiOutHandle) + ' and close the device + Midi.MIDI_OutClose(_midiOutHandle) + ... + Private Sub SendShortMessage(message As Integer) + MIDI_OutShortMsg(_midiOutHandle, message) + End Sub + + Private Sub SendSysExMessage(data() As Byte) + Dim header As New MIDI_HEADER(data) + header.Prepare(False, _midiOutHandle) + ' If the header was perpared successfully. + If header.HeaderPtr <> IntPtr.Zero Then + ' send a system-exclusive message to the output device + Midi.MIDI_OutLongMsg(_midiOutHandle, header.HeaderPtr) + End If + End Sub + + Public Sub MyMidiProc(handle As IntPtr, msg As MIDIMessage, instance As IntPtr, param1 As IntPtr, param2 As IntPtr) + ' handle all Midi messages here + If msg = MIDIMessage.MOM_OPEN Then + ' nothing to do + Else + If msg = MIDIMessage.MOM_CLOSE Then + ' handle is from now on invalid + Else + If msg = MIDIMessage.MOM_DONE Then + ' process the message... + ' param1 will contain the pointer to the MIDI_HEADER + Dim header As New MIDI_HEADER(param1) + ' process the header if needed + ... + ' and finally unprepare the header + header.Unprepare(False, handle) + End If + End If + End If + End Sub + + + + + + Closes the specified MIDI output device. + + Handle to the MIDI output device. If the function is successful, the handle is no longer valid after the call to this function. + Returns 0 if successful or an error code otherwise. For possible error values see . + If there are output buffers that have been sent by using the function and have not been returned to the application, the close operation will fail. + To mark all pending buffers as being done, use the function. + + + + + Connects a MIDI input device to a MIDI thru or output device, or connects a MIDI thru device to a MIDI output device. + + Handle to a MIDI input device or a MIDI thru device (for thru devices, this handle must belong to a MIDI output device). + Handle to the MIDI output device or thru device. + Returns 0 if successful or an error code otherwise. For possible error values see . + After calling this function, the MIDI input device receives event data in an MIM_DATA message whenever a message with the same event data is sent to the output device driver. + A thru driver is a special form of MIDI output driver. The system will allow only one MIDI output device to be connected to a MIDI input device, but multiple MIDI output devices can be connected to a MIDI thru device. + Whenever the given MIDI input device receives event data in an MIM_DATA message, a message with the same event data is sent to the given output device driver (or through the thru driver to the output drivers). + + + + + Disconnects a MIDI input device from a MIDI thru or output device, or disconnects a MIDI thru device from a MIDI output device. + + Handle to a MIDI input device or a MIDI thru device. + Handle to the MIDI output device to be disconnected. + Returns 0 if successful or an error code otherwise. For possible error values see . + MIDI input, output, and thru devices can be connected by using the function. + Thereafter, whenever the MIDI input device receives event data in an MIM_DATA message, a message with the same event data is sent to the output device driver (or through the thru driver to the output drivers). + + + + + Starts MIDI input on the specified MIDI input device. + + Handle to the MIDI input device. + Returns 0 if successful or an error code otherwise. For possible error values see . + + This function resets the time stamp to zero. Time stamp values for subsequently received messages are relative to the time that this function was called. + All messages except system-exclusive messages are sent directly to the client when they are received. System-exclusive messages are placed in the buffers supplied by the function. + If there are no buffers in the queue, the system-exclusive data is thrown away without notification to the client and input continues. + Buffers are returned to the client when they are full, when a complete system-exclusive message has been received, or when the function is used. + The member of the structure will contain the actual data received. + Calling this function when input is already started has no effect, and the function returns zero. + + + + + Stops MIDI input on the specified MIDI input device. + + Handle to the MIDI input device. + Returns 0 if successful or an error code otherwise. For possible error values see . + + If there are any system-exclusive messages or stream buffers in the queue, the current buffer is marked as done (the member of the structure will contain the actual data received), but any empty buffers in the queue remain there and are not marked as done. + Calling this function when input is not started has no effect, and the function returns zero. + + + + + Stops input on a given MIDI input device. + + Handle to the MIDI input device. + Returns 0 if successful or an error code otherwise. For possible error values see . + This function returns all pending input buffers to the callback function and sets the flag in the Flags member of the structure. + + + + Turns off all notes on all MIDI channels for the specified MIDI output device. + + Handle to the MIDI output device. + Returns 0 if successful or an error code otherwise. For possible error values see . + + Any pending system-exclusive or stream output buffers are returned to the callback function and the MHDR_DONE flag is set in the Flags member of the structure. + Terminating a system-exclusive message without sending an EOX (end-of-exclusive) byte might cause problems for the receiving device. + The function does not send an EOX byte when it terminates a system-exclusive message — applications are responsible for doing this. + To turn off all notes, a note-off message for each note in each channel is sent. In addition, the sustain controller is turned off for each channel. + + + + + Sends a short MIDI message to the specified MIDI output device. + + Handle to the MIDI output device. + MIDI message. The message is packed into a double word value with the first byte of the message in the low-order byte. The message is packed into this parameter as follows: + High-Word: High-order byte: Not used. Low-order byte: The second byte of MIDI data (when needed). + Low-Word: High-order byte: The first byte of MIDI data (when needed). Low-order byte: The MIDI status. + The two MIDI data bytes are optional, depending on the MIDI status byte. When a series of messages have the same status byte, the status byte can be omitted from messages after the first one in the series, creating a running status. + + Returns 0 if successful or an error code otherwise. For possible error values see . + + This function is used to send any MIDI message except for system-exclusive or stream messages. + This function might not return until the message has been sent to the output device. You can send short messages while streams are playing on the same device (although you cannot use a running status in this case). + You might used the class to construct and or pack the message with it's components. + + + + private MIDIOUTPROC _midiProc; + private IntPtr _midiOutHandle; + ... + // Open the Midi device #2 + _midiProc = new MIDIOUTPROC(MyMidiProc); + MIDIError ret = Midi.MIDI_OutOpen(ref _midiOutHandle, 2, _midiProc, 0); + if (ret == MIDIError.MIDI_OK) + { + // device opened and ready + } + ... + // When not needed anymore...stop the device + Midi.MIDI_OutReset(_midiOutHandle); + // and close the device + Midi.MIDI_OutClose(_midiOutHandle); + ... + private void SendShortMessage(int message) + { + MIDI_OutShortMsg(_midiOutHandle, message); + } + + private void SendSysExMessage(byte[] data) + { + MIDI_HEADER header = new MIDI_HEADER(data); + header.Prepare(false, _midiOutHandle); + // If the header was perpared successfully. + if (header.HeaderPtr != IntPtr.Zero) + { + // send a system-exclusive message to the output device + Midi.MIDI_OutLongMsg(_midiOutHandle, header.HeaderPtr); + } + } + + public void MyMidiProc(IntPtr handle, MIDIMessage msg, IntPtr instance, IntPtr param1, IntPtr param2) + { + // handle all Midi messages here + if (msg == MIDIMessage.MOM_OPEN) + { + // nothing to do + } + else if (msg == MIDIMessage.MOM_CLOSE) + { + // handle is from now on invalid + } + else if (msg == MIDIMessage.MOM_DONE) + { + // process the message... + // param1 will contain the pointer to the MIDI_HEADER + MIDI_HEADER header = new MIDI_HEADER(param1); + // process the header if needed + ... + // and finally unprepare the header + header.Unprepare(false, handle); + } + } + + + Private _midiProc As MIDIOUTPROC + Private _midiOutHandle As IntPtr + ... + ' Open the Midi device #2 + _midiProc = New MIDIOUTPROC(MyMidiProc) + Dim ret As MIDIError = Midi.MIDI_OutOpen(_midiOutHandle, 2, _midiProc, 0) + If ret = MIDIError.MIDI_OK Then + ' device opened and ready + End If + ... + ' when not needed anymore...stop the device + Midi.MIDI_OutReset(_midiOutHandle) + ' and close the device + Midi.MIDI_OutClose(_midiOutHandle) + ... + Private Sub SendShortMessage(message As Integer) + MIDI_OutShortMsg(_midiOutHandle, message) + End Sub + + Private Sub SendSysExMessage(data() As Byte) + Dim header As New MIDI_HEADER(data) + header.Prepare(False, _midiOutHandle) + ' If the header was perpared successfully. + If header.HeaderPtr <> IntPtr.Zero Then + ' send a system-exclusive message to the output device + Midi.MIDI_OutLongMsg(_midiOutHandle, header.HeaderPtr) + End If + End Sub + + Public Sub MyMidiProc(handle As IntPtr, msg As MIDIMessage, instance As IntPtr, param1 As IntPtr, param2 As IntPtr) + ' handle all Midi messages here + If msg = MIDIMessage.MOM_OPEN Then + ' nothing to do + Else + If msg = MIDIMessage.MOM_CLOSE Then + ' handle is from now on invalid + Else + If msg = MIDIMessage.MOM_DONE Then + ' process the message... + ' param1 will contain the pointer to the MIDI_HEADER + Dim header As New MIDI_HEADER(param1) + ' process the header if needed + ... + ' and finally unprepare the header + header.Unprepare(False, handle) + End If + End If + End If + End Sub + + + + + + Sends a system-exclusive MIDI message to the specified MIDI output device. + + Handle to the MIDI output device. + Pointer to a structure that identifies the MIDI buffer. + Returns 0 if successful or an error code otherwise. For possible error values see . + + + private MIDIOUTPROC _midiProc; + private IntPtr _midiOutHandle; + ... + // Open the Midi device #2 + _midiProc = new MIDIOUTPROC(MyMidiProc); + MIDIError ret = Midi.MIDI_OutOpen(ref _midiOutHandle, 2, _midiProc, 0); + if (ret == MIDIError.MIDI_OK) + { + // device opened and ready + } + ... + // When not needed anymore...stop the device + Midi.MIDI_OutReset(_midiOutHandle); + // and close the device + Midi.MIDI_OutClose(_midiOutHandle); + ... + private void SendShortMessage(int message) + { + MIDI_OutShortMsg(_midiOutHandle, message); + } + + private void SendSysExMessage(byte[] data) + { + MIDI_HEADER header = new MIDI_HEADER(data); + header.Prepare(false, _midiOutHandle); + // If the header was perpared successfully. + if (header.HeaderPtr != IntPtr.Zero) + { + // send a system-exclusive message to the output device + Midi.MIDI_OutLongMsg(_midiOutHandle, header.HeaderPtr); + } + } + + public void MyMidiProc(IntPtr handle, MIDIMessage msg, IntPtr instance, IntPtr param1, IntPtr param2) + { + // handle all Midi messages here + if (msg == MIDIMessage.MOM_OPEN) + { + // nothing to do + } + else if (msg == MIDIMessage.MOM_CLOSE) + { + // handle is from now on invalid + } + else if (msg == MIDIMessage.MOM_DONE) + { + // process the message... + // param1 will contain the pointer to the MIDI_HEADER + MIDI_HEADER header = new MIDI_HEADER(param1); + // process the header if needed + ... + // and finally unprepare the header + header.Unprepare(false, handle); + } + } + + + Private _midiProc As MIDIOUTPROC + Private _midiOutHandle As IntPtr + ... + ' Open the Midi device #2 + _midiProc = New MIDIOUTPROC(MyMidiProc) + Dim ret As MIDIError = Midi.MIDI_OutOpen(_midiOutHandle, 2, _midiProc, 0) + If ret = MIDIError.MIDI_OK Then + ' device opened and ready + End If + ... + ' when not needed anymore...stop the device + Midi.MIDI_OutReset(_midiOutHandle) + ' and close the device + Midi.MIDI_OutClose(_midiOutHandle) + ... + Private Sub SendShortMessage(message As Integer) + MIDI_OutShortMsg(_midiOutHandle, message) + End Sub + + Private Sub SendSysExMessage(data() As Byte) + Dim header As New MIDI_HEADER(data) + header.Prepare(False, _midiOutHandle) + ' If the header was perpared successfully. + If header.HeaderPtr <> IntPtr.Zero Then + ' send a system-exclusive message to the output device + Midi.MIDI_OutLongMsg(_midiOutHandle, header.HeaderPtr) + End If + End Sub + + Public Sub MyMidiProc(handle As IntPtr, msg As MIDIMessage, instance As IntPtr, param1 As IntPtr, param2 As IntPtr) + ' handle all Midi messages here + If msg = MIDIMessage.MOM_OPEN Then + ' nothing to do + Else + If msg = MIDIMessage.MOM_CLOSE Then + ' handle is from now on invalid + Else + If msg = MIDIMessage.MOM_DONE Then + ' process the message... + ' param1 will contain the pointer to the MIDI_HEADER + Dim header As New MIDI_HEADER(param1) + ' process the header if needed + ... + ' and finally unprepare the header + header.Unprepare(False, handle) + End If + End If + End If + End Sub + + + + + + Prepares a buffer for MIDI input. + + Handle to the MIDI input device. + Pointer to a structure that identifies the buffer to be prepared. + Returns 0 if successful or an error code otherwise. For possible error values see . + + Preparing a header that has already been prepared has no effect, and the function returns zero. + After the header has been prepared, do not modify the buffer. To free the buffer, use the function. + Before using this function, you must set the data, bufferLength, and flags members of the structure. The flags member must be set to zero. + For convenience the might also be used, which calls the method internally and returns the header pointer in the member. + + + + private MIDIINPROC _midiInProc; + private IntPtr _midiInHandle; + ... + private void StartRecording() + { + _midiInProc = new MIDIINPROC(MyMidiInProc); + MIDIError ret = Midi.MIDI_InOpen(ref _midiInHandle, 1, _midiInProc, 0, MIDIFlags.MIDI_IO_STATUS); + if (ret == MIDIError.MIDI_OK) + { + // supply the device with 2 buffers + AddSysExBuffer(_midiInHandle, 1024); + AddSysExBuffer(_midiInHandle, 1024); + ret = Midi.MIDI_InStart(_midiInHandle); + } + } + + // prepare receiving system-exclusive messages + private void AddSysExBuffer(IntPtr handle, int size) + { + // prepare a empty midi header + MIDI_HEADER header = new MIDI_HEADER(size); + header.Prepare(true, handle); + // If the header was perpared successfully. + if (header.HeaderPtr != IntPtr.Zero) + { + // Add the buffer to the InputDevice. + Midi.MIDI_InAddBuffer(handle, header.HeaderPtr); + } + } + + private void MyMidiInProc(IntPtr handle, MIDIMessage msg, IntPtr instance, IntPtr param1, IntPtr param2) + { + // handle all Midi messages here + if (msg == MIDIMessage.MIM_DATA) + { + // process the short message... + int p1 = param1.ToInt32(); + int p2 = param2.ToInt32(); + ... + Console.WriteLine("Msg={0}\r\nParam1={1}\r\nParam2={2}" , msg, p1, p2); + } + else if (msg == MIDIMessage.MIM_LONGDATA) + { + // process the system-exclusive message... + MIDI_HEADER header = new MIDI_HEADER(param1); + if (header.IsDone) + { + byte[] data = header.Data; + ... + Console.WriteLine(header.ToString()); + } + // must unprepare the processed header + header.Unprepare(true, handle); + // add a new buffer + // we must constantly provide new buffers until we finished recording + AddSysExBuffer(handle, 1024); + } + ... + } + + + Private _midiInProc As MIDIINPROC + Private _midiInHandle As IntPtr + ... + Private Sub StartRecording() + _midiInProc = New MIDIINPROC(AddressOf MyMidiInProc) + Dim ret As MIDIError = Midi.MIDI_InOpen(_midiInHandle, 1, _midiInProc, 0, MIDIFlags.MIDI_IO_STATUS) + If ret = MIDIError.MIDI_OK Then + ' supply the device with 2 buffers + AddSysExBuffer(_midiInHandle, 1024) + AddSysExBuffer(_midiInHandle, 1024) + ret = Midi.MIDI_InStart(_midiInHandle) + End If + End Sub + + ' prepare receiving system-exclusive messages + Private Sub AddSysExBuffer(handle As IntPtr, size As Integer) + ' prepare a empty midi header + Dim header As New MIDI_HEADER(size) + header.Prepare(True, handle) + ' If the header was perpared successfully. + If header.HeaderPtr <> IntPtr.Zero Then + ' Add the buffer to the InputDevice. + Midi.MIDI_InAddBuffer(handle, header.HeaderPtr) + End If + End Sub + + Private Sub MyMidiInProc(handle As IntPtr, msg As MIDIMessage, instance As IntPtr, param1 As IntPtr, param2 As IntPtr) + ' handle all Midi messages here + If msg = MIDIMessage.MIM_DATA Then + ' process the short message... + Dim p1 As Integer = param1.ToInt32() + Dim p2 As Integer = param2.ToInt32() + ... + Console.WriteLine("Msg={0}" + ControlChars.Cr + ControlChars.Lf + "Param1={1}" + ControlChars.Cr + ControlChars.Lf + "Param2={2}", msg, p1, p2) + Else + If msg = MIDIMessage.MIM_LONGDATA Then + ' process the system-exclusive message... + Dim header As New MIDI_HEADER(param1) + If header.IsDone Then + Dim data As Byte() = header.Data + ... + Console.WriteLine(header.ToString()) + End If + ' must unprepare the processed header + header.Unprepare(True, handle) + ' add a new buffer + ' we must constantly provide new buffers until we finished recording + AddSysExBuffer(handle, 1024) + End If + ... + End If + End Sub + + + + + + Cleans up the preparation performed by the function. + + Handle to the MIDI input device. + Pointer to a structure identifying the buffer to be cleaned up. + Returns 0 if successful or an error code otherwise. For possible error values see . + + This function is complementary to . You must use this function before freeing the buffer. After passing a buffer to the device driver by using the function, you must wait until the driver is finished with the buffer before using . + Unpreparing a buffer that has not been prepared has no effect, and the function returns 0. + For convenience the might also be used, which calls this method internally. + In order to convert an IntPtr (e.g. as given in the with the or as param1) back to a structure use the appropriate constructor overload of the class taking a headerPtr. + + + + private MIDIINPROC _midiInProc; + private IntPtr _midiInHandle; + ... + private void StartRecording() + { + _midiInProc = new MIDIINPROC(MyMidiInProc); + MIDIError ret = Midi.MIDI_InOpen(ref _midiInHandle, 1, _midiInProc, 0, MIDIFlags.MIDI_IO_STATUS); + + if (ret == MIDIError.MIDI_OK) + { + // supply the device with 2 buffers + AddSysExBuffer(_midiInHandle, 1024); + AddSysExBuffer(_midiInHandle, 1024); + + ret = Midi.MIDI_InStart(_midiInHandle); + } + } + + // prepare receiving system-exclusive messages + public void AddSysExBuffer(IntPtr handle, int size) + { + // prepare a empty midi header + MIDI_HEADER header = new MIDI_HEADER(size); + header.Prepare(true, handle); + // If the header was perpared successfully. + if (header.HeaderPtr != IntPtr.Zero) + { + // Add the buffer to the InputDevice. + Midi.MIDI_InAddBuffer(handle, header.HeaderPtr); + } + } + + private void MyMidiInProc(IntPtr handle, MIDIMessage msg, IntPtr instance, IntPtr param1, IntPtr param2) + { + // handle all Midi messages here + if (msg == MIDIMessage.MIM_DATA) + { + // process the short message... + // on Win32 system the param1 and param2 values might be converted like this: + int p1 = param1.ToInt32(); + int p2 = param2.ToInt32(); + Console.WriteLine( "Msg={0}\r\nParam1={1}\r\nParam2={2}" , msg, p1, p2); + } + else if (msg == MIDIMessage.MIM_LONGDATA) + { + // process the system-exclusive message... + MIDI_HEADER header = new MIDI_HEADER(param1); + if (header.IsDone) + { + byte[] data = header.Data; + ... + Console.WriteLine( header.ToString() ); + } + header.Unprepare(true, handle); + + // add a new buffer + // since we should constantly provide new buffers until we finished recording + AddSysExBuffer(handle, 1024); + } + ... + } + + + + + + Sends an input buffer to a specified opened MIDI input device. This function is used for system-exclusive messages. + + Handle to the MIDI input device. + Pointer to a structure that identifies the buffer. + Returns 0 if successful or an error code otherwise. For possible error values see . + + When the buffer is filled, it is sent back to the application (see ). + The buffer must be prepared by using the function before it is passed to this function. + For convenience the might also be used, which calls internally and provides the prepared header pointer in it's member. + In order to convert an IntPtr (e.g. as given in the with the or as param1) back to a structure use the appropriate constructor overload of the class taking a headerPtr. + + + + private MIDIINPROC _midiInProc; + private IntPtr _midiInHandle; + ... + private void StartRecording() + { + _midiInProc = new MIDIINPROC(MyMidiInProc); + MIDIError ret = Midi.MIDI_InOpen(ref _midiInHandle, 1, _midiInProc, 0, MIDIFlags.MIDI_IO_STATUS); + + if (ret == MIDIError.MIDI_OK) + { + // supply the device with 2 buffers + AddSysExBuffer(_midiInHandle, 1024); + AddSysExBuffer(_midiInHandle, 1024); + + ret = Midi.MIDI_InStart(_midiInHandle); + } + } + + // prepare receiving system-exclusive messages + public void AddSysExBuffer(IntPtr handle, int size) + { + // prepare a empty midi header + MIDI_HEADER header = new MIDI_HEADER(size); + header.Prepare(true, handle); + // If the header was perpared successfully. + if (header.HeaderPtr != IntPtr.Zero) + { + // Add the buffer to the InputDevice. + Midi.MIDI_InAddBuffer(handle, header.HeaderPtr); + } + } + + private void MyMidiInProc(IntPtr handle, MIDIMessage msg, IntPtr instance, IntPtr param1, IntPtr param2) + { + // handle all Midi messages here + if (msg == MIDIMessage.MIM_DATA) + { + // process the short message... + // on Win32 system the param1 and param2 values might be converted like this: + int p1 = param1.ToInt32(); + int p2 = param2.ToInt32(); + Console.WriteLine( "Msg={0}\r\nParam1={1}\r\nParam2={2}" , msg, p1, p2); + } + else if (msg == MIDIMessage.MIM_LONGDATA) + { + // process the system-exclusive message... + MIDI_HEADER header = new MIDI_HEADER(param1); + if (header.IsDone) + { + byte[] data = header.Data; + ... + Console.WriteLine( header.ToString() ); + } + header.Unprepare(true, handle); + + // add a new buffer + // since we should constantly provide new buffers until we finished recording + AddSysExBuffer(handle, 1024); + } + ... + } + + + + + + Prepares a MIDI system-exclusive or stream buffer for output. + + Handle to the MIDI output device. + Pointer to a structure that identifies the buffer to be prepared. + Returns 0 if successful or an error code otherwise. For possible error values see . + + A stream buffer cannot be larger than 64K. + Preparing a header that has already been prepared has no effect, and the function returns 0. + After the header has been prepared, do not modify the buffer. To free the buffer, use the function. + Before using this function, you must set the data, bufferLength, and flags members of the structure. The flags member must be set to zero. + For convenience the might also be used, which calls internally and provides the prepared header pointer in it's member. + In order to convert an IntPtr (e.g. as given in the with the or as param1) back to a structure use the appropriate constructor overload of the class taking a headerPtr. + + + + + Cleans up the preparation performed by the midiOutPrepareHeader function. + + Handle to the MIDI output device. + Pointer to a structure identifying the buffer to be cleaned up. + Returns 0 if successful or an error code otherwise. For possible error values see . + + This function is complementary to the function. You must call before freeing the buffer. + After passing a buffer to the device driver with the function, you must wait until the device driver is finished with the buffer before calling . + Unpreparing a buffer that has not been prepared has no effect, and the function returns 0. + For convenience the might also be used, which calls internally and provides the prepared header pointer in it's member. + In order to convert an IntPtr (e.g. as given in the with the or as param1) back to a structure use the appropriate constructor overload of the class taking a headerPtr. + + + + + Sends a message to the MIDI device driver (input). + + Identifier of the MIDI device that receives the message (must be a handle type). + Message to send (e.g. one of the values). + Message parameter 1. + Message parameter 2. + Returns the value returned by the audio device driver. + This function is used only for driver-specific messages that are not supported by the MIDI API. + + + + Sends a message to the MIDI device driver (output). + + Identifier of the MIDI device that receives the message (must be a handle type). + Message to send (e.g. one of the values). + Message parameter 1. + Message parameter 2. + Returns the value returned by the audio device driver. + This function is used only for driver-specific messages that are not supported by the MIDI API. + + + + Converts a MIDI note number to its corresponding frequency. + + The number of the note to convert. + The frequency of the specified note in Hz. + MIDI notes will typically be numbered from 0 (C-1) to 127 (G8). + The reference is the standard pitch (A3) which has the number 69 and represents 440 Hz. + See the enummeration for possible note values. + + + + // the following code will return 440Hz for the C + int freq = Utils.NoteToFrequency(69); + + + ' the following code will return 440Hz for the C + Dim freq As Integer = Utils.NoteToFrequency(69) + + + + + + This class represents a Midi short (data) message as for example received in a message of a . + + You might use the class to pack (encode, construct) or unpack (decode) any Midi short message. + Use this class with the method to send a message to an output device. Use the property in that case to get the constructed message value. + Use this class with the message of a to decode the received message. + + + Using the MidiShortMessage with an MIDIINPROC: + + private MIDIINPROC _midiProc; + private int _midiInHandle; + ... + // Open the Midi device #2 + _midiProc = new MIDIINPROC(MyMidiProc); + MIDIError ret = Midi.MIDI_InOpen(ref _midiInHandle, 2, _midiProc, IntPtr.Zero, MIDIFlags.MIDI_IO_STATUS); + if (ret == MIDIError.MIDI_OK) + { + // supply the device with 2 buffers + AddSysExBuffer(_midiInHandle, 1024); + AddSysExBuffer(_midiInHandle, 1024); + // Start the device + ret = Midi.MIDI_InStart(_midiInHandle); + } + ... + // when not needed anymore...stop the device + Midi.MIDI_InReset(_midiInHandle); + // and close the device + Midi.MIDI_InClose(_midiInHandle); + ... + // prepare receiving system-exclusive messages + private void AddSysExBuffer(IntPtr handle, int size) + { + // prepare a empty midi header + MIDI_HEADER header = new MIDI_HEADER(size); + header.Prepare(true, handle); + // If the header was perpared successfully. + if (header.HeaderPtr != IntPtr.Zero) + { + // Add the buffer to the InputDevice. + Midi.MIDI_InAddBuffer(handle, header.HeaderPtr); + } + } + ... + private MidiShortMessage _shortMsg = null; + private MidiSysExMessage _sysExMsg = null; + + public void MyMidiProc(IntPtr handle, MIDIMessage msg, IntPtr instance, IntPtr param1, IntPtr param2) + { + // handle all Midi messages here + if(msg == MIDIMessage.MIM_OPEN) + { + // nothing to do + } + else if(msg == MIDIMessage.MIM_CLOSE) + { + // handle is from now on invalid + } + else if(msg == MIDIMessage.MIM_DATA) + { + // process the message... + _shortMsg = new MidiShortMessage(param1, param2, _shortMsg); + Console.WriteLine(_shortMsg.ToString()); + } + else if(msg == MIDIMessage.MIM_MOREDATA) + { + // we are not fast enough in this callback to keep up... + // the input device is sending messages to fast + ... + } + else if(msg == MIDIMessage.MIM_LONGDATA) + { + // process the message... + // param1 will contain the pointer to the MIDI_HEADER + _sysExMsg = new MidiSysExMessage(true, handle, param1, _sysExMsg); + if (_sysExMsg.IsDone) + { + Console.WriteLine(_sysExMsg.ToString()); + } + // add a new buffer + // since we must constantly provide new buffers until we finished recording + AddSysExBuffer(handle, 1024); + } + else if(msg == MIDIMessage.MIM_ERROR) + { + // process the invalid message... + ... + } + else if(msg == MIDIMessage.MIM_LONGERROR) + { + // process the invalid message... + // param1 will contain the pointer to the MIDI_HEADER + MIDI_HEADER header = new MIDI_HEADER(param1); + header.Unprepare(true, handle); + // add a new buffer + // since we should constantly provide new buffers until we finished recording + AddSysExBuffer(handle, 1024); + } + } + + + Private _midiInProc As MIDIINPROC + Private _midiInHandle As IntPtr + ... + ' Open the Midi device #2 + _midiProc = New MIDIINPROC(AddressOf MyMidiProc) + Dim ret As MIDIError = Midi.MIDI_InOpen(_midiInHandle, 2, _midiProc, IntPtr.Zero, MIDIFlags.MIDI_IO_STATUS) + If ret = MIDIError.MIDI_OK Then + ' supply the device with 2 buffers + AddSysExBuffer(_midiInHandle, 1024) + AddSysExBuffer(_midiInHandle, 1024) + ' Start the device + ret = Midi.MIDI_InStart(_midiInHandle) + End If + ... + ' when not needed anymore...stop the device + Midi.MIDI_InReset(_midiInHandle) + ' and close the device + Midi.MIDI_InClose(_midiInHandle) + ... + Private _shortMsg As MidiShortMessage = Nothing + Private _sysExMsg As MidiSysExMessage = Nothing + ... + Public Sub MyMidiProc(handle As IntPtr, msg As MIDIMessage, instance As IntPtr, param1 As IntPtr, param2 As IntPtr) + ' handle all Midi messages here + If msg = MIDIMessage.MIM_OPEN Then + ' nothing to do + Else + If msg = MIDIMessage.MIM_CLOSE Then + ' handle is from now on invalid + Else + If msg = MIDIMessage.MIM_DATA Then + ' process the message... + _shortMsg = New MidiShortMessage(param1, param2, _shortMsg) + Console.WriteLine(_shortMsg.ToString()) + Else + If msg = MIDIMessage.MIM_MOREDATA Then + ' we are not fast enough in this callback to keep up... + ' the input device is sending messages to fast + ... + Else + If msg = MIDIMessage.MIM_LONGDATA Then + ' process the message... + ' param1 will contain the pointer to the MIDI_HEADER + _sysExMsg = New MidiSysExMessage(True, handle, param1, _sysExMsg) + If _sysExMsg.IsDone Then + Console.WriteLine(_sysExMsg.ToString()) + End If + ' add a new buffer + ' since we must constantly provide new buffers until we finished recording + AddSysExBuffer(handle, 1024) + Else + If msg = MIDIMessage.MIM_ERROR Then + ' process the invalid message... + ... + Else + If msg = MIDIMessage.MIM_LONGERROR Then + ' process the invalid message... + ' param1 will contain the pointer to the MIDI_HEADER + Dim header As New MIDI_HEADER(param1) + header.Unprepare(True, handle) + ' add a new buffer + ' since we should constantly provide new buffers until we finished recording + AddSysExBuffer(handle, 1024) + End If + End If + End If + End If + End If + End If + End If + End Sub + + + + + + Default constructor. + + You might use this one together with the method to construct your own Midi data message. + + + + Creates a new instance of the MidiShortMessage. + + The MIDI message that was received. + The timestamp that the message was received by the input device driver. + + You might use this constuctor for example in your when receiving a message. + MIDI messages received from a MIDI input port have running status disabled; each message is expanded to include the MIDI status byte. + + + + + Creates a new instance of the MidiShortMessage and also evaluates a previous short message.. + + The MIDI message that was received. + The timestamp that the message was received by the input device driver. + The previous short message received (e.g. in order to check, if a message need to be paired - which is not done automatically here!). + + You might use this constuctor for example in your when receiving a message. + MIDI messages received from a MIDI input port have running status disabled; each message is expanded to include the MIDI status byte. + Note: Some ControlChange messages might actually use two short messages (e.g. the ) to support paired values with a higher resolution (16384 instead of 128 values). + In such case two messages will be send, where one contains the the LSB value (single steps) in it's byte and the other on the MSB value (128th steps) in it's byte. + For this special case it might be useful to keep in your handler always the current and the last (previous) message. + Use this overload to always keep your previous message with the current short message. + NOTE: The property will only be set in case this current message and the are having the same (otherwise all previous messages would be links together and memory wil simply increase and increase, since the Garbage Collector would never release any un-needed messages)! + In case of real-time messages the the will also not be set. + To access the single value assigned to the / access the property. + You might use the , resp. the method to retrieve a combined value from two short messages resp. two data value. + + + + + Creates a new instance of the MidiShortMessage. + + The status to use. + The Midi channel number to use (0 to 15). + The data 1 value to use. + The data 2 value to use. + The time stamp to use (expressed in milliseconds or 0). + You might use this to construct for example a channel message. + + + + Creates a new instance of the MidiShortMessage. + + The Midi status byte value to use. + The data 1 value to use. + The data 2 value to use. + The data 3 value to use (typically never used). + The time stamp to use (expressed in milliseconds or 0 if not applicable). + You might use this to construct for example a channel message. + + + + Defines that this message is related to a continuous controller. + + Set to , if this message contains the MSB (coarse) controller value - else this message contains the LSB (fine) controller value. + Set to , if the contains the MSB (coarse) controller value - else the contains the LSB (fine) controller value. + If you set both parameters to the message is not related to a continuous controller (default). + In addition this message is only set to be a continuous controller message, if the exists and it's also has a value of and the is the same. + + + + + Returns a combined paired value from a MSB and a LSB data byte. + + The MSB (most significant) data byte value. + The LSB (least significant) data byte value. + The combined data value ranging from 0 to 16383 (128*128 values). + + The byte will contain the lower 7-bit value (single steps) and the byte the upper 7-bit value (128th steps) both ranging from 0 to 128. + Some Midi data messages might actually use two sub-sequent short messages to construct a paired message representing a single value range (e.g. the with a ). + This to support paired values with a higher resolution (16384 instead of 128 values). The same might apply the the controller value itself. + In such case two short messages will be send, where one contains the LSB value (single steps) in it's or byte and the other message contains the MSB value (128th steps) in it's or byte. + Typically the messages with a of and with a value between 0 and 31 (MSB) are paired with a message of a value between 32 and 63 (LSB). + But also a value of 98 (LSB) will be paired with a value of 99 (MSB) as well as a value of 100 (LSB) will be paired with a value of 101 (MSB). + Other pairs might be hardware specific. + So it might be useful to keep in your handler always the current and the last message. + The resulting combined data value will be constructed like this: dataMSB=0xxxxxxx, dataLSB=0yyyyyyy = paired=00xxxxxxxyyyyyyy. + You might also use the resp. the method to retrieve a combined value from two short messages resp. two data value. + + + + + Returns a combined paired value from a MSB and a LSB . + + The containing the MSB (most significant) byte value. + The containing the LSB (least significant) byte value. + The combined data value ranging from 0 to 16383 (128*128 values). + + The byte of the message will contain the lower 7-bit value (single steps) and the byte of the message the upper 7-bit value (128th steps) both ranging from 0 to 128. + Some Midi data messages might actually use two sub-sequent short messages to construct a paired message representing a single value range (e.g. the with a ). + This to support paired values with a higher resolution (16384 instead of 128 values). The same might apply the the controller value itself. + In such case two short messages will be send, where one contains the LSB value (single steps) in it's byte and the other message contains the MSB value (128th steps) in it's byte. + Typically the messages with a of and with a value between 0 and 31 (MSB) are paired with a message of a value between 32 and 63 (LSB). + But also a value of 98 (LSB) will be paired with a value of 99 (MSB) as well as a value of 100 (LSB) will be paired with a value of 101 (MSB). + Other pairs might be hardware specific. + So it might be useful to keep in your handler always the current and the last message. + The resulting combined data value will be constructed like this: dataMSB=0xxxxxxx, dataLSB=0yyyyyyy = paired=00xxxxxxxyyyyyyy. + You might also use the resp. the method to retrieve a combined value from two short messages resp. two data value. + + + + + Returns a combined paired value from a MSB and a LSB . + + The containing the MSB (most significant) byte value. + The containing the LSB (least significant) byte value. + The combined data value ranging from 0 to 16383 (128*128 values). + + The byte of the message will contain the lower 7-bit value (single steps) and the byte of the message the upper 7-bit value (128th steps) both ranging from 0 to 128. + Some Midi data messages might actually use two sub-sequent short messages to construct a paired message representing a single value range (e.g. the with a ). + This to support paired values with a higher resolution (16384 instead of 128 values). The same might apply the the controller value itself. + In such case two short messages will be send, where one contains the LSB value (single steps) in it's byte and the other message contains the MSB value (128th steps) in it's byte. + Typically the messages with a of and with a value between 0 and 31 (MSB) are paired with a message of a value between 32 and 63 (LSB). + But also a value of 98 (LSB) will be paired with a value of 99 (MSB) as well as a value of 100 (LSB) will be paired with a value of 101 (MSB). + Other pairs might be hardware specific. + So it might be useful to keep in your handler always the current and the last message. + The resulting combined data value will be constructed like this: dataMSB=0xxxxxxx, dataLSB=0yyyyyyy = paired=00xxxxxxxyyyyyyy. + You might also use the resp. the method to retrieve a combined value from two short messages resp. two data value. + + + + + Constructs a new Midi data message. + + The status to use. + The Midi channel number to use (0 to 15). + The data 1 value to use. + The data 2 value to use. + The time stamp to use (expressed in milliseconds or 0 if not applicable). + You might use this to construct for example a channel message. + + + + Constructs a new Midi data message. + + The Midi status byte value to use. + The data 1 value to use. + The data 2 value to use. + The data 3 value to use (typically never used). + The time stamp to use (expressed in milliseconds or 0 if not applicable). + You might use this to construct for example a channel message. + + + + Constructs a new Midi data message. + + The message value to use. + The time stamp to use (expressed in milliseconds or 0 if not applicable). + You might use this to construct for example a channel message. + + + + Constructs a new Midi data message. + + The message value to use. + The time stamp to use (expressed in milliseconds or 0 if not applicable). + You might use this to construct for example a channel message. + + + + Returns the string representation of the Midi short message. + + The string representing the Midi short message (same as ToString("G")). + + + + Returns the string representation of the Midi short message. + + The format to use (one of the following): + + "G"Combi-Format: Timestamp, Type, Channel, Status, Data in full text - same as "{T}\t{M} {C}\t{S}\t{D}" (for Channel messages) resp. "{T}\t{M}\t{S}\t{D}" (for other messages). + "g"Combi-Format: Timestamp, Type, Channel, Status, Data as numerical values - same as "{t}\t{m} {C}\t{s}\t{d}" (for Channel messages) resp. "{t}\t{m}\t{s}\t{d}" (for other messages). + "X"Combi-Format: Timespan and Message as hexadecimal values (big hex) - same as "{U} {A} {H}". + "x"Combi-Format: Timespan and Message as hexadecimal values (small hex) - same as "{u} {a} {h}". + "Y"Combi-Format: Message as hexadecimal values (big hex) - same as "{A} {H}". + "y"Combi-Format: Message as hexadecimal values (small hex) - same as "{a} {h}". + "T"Timespan only. + "t"Timestamp only. + "U"Timestamp only as hexadecimal values (big hex). + "u"Timestamp only as hexadecimal values (small hex). + "M"MessageType only in full text. + "m"MessageType as numerical values. + "S"StatusType only in full text. + "s"StatusType only as numerical value. + "A"Status only as hexadecimal values (big hex). + "a"Status only as hexadecimal values (small hex). + "C"Channel only as numerical value. + "D"Data only in full text. + "d"Data only as numerical value. + "H"Data only as hexadecimal values (big hex). + "h"Data only as hexadecimal values (small hex). + + You might also combine the single values into a full format string when enclosed in brackets (e.g. "Time={T}: Msg={M}, Chan={C}, Status={S}, Data={D}"). + In such case all the format values enclosed in brackets will be replaced by the above value representations. This allows you to format your individual message string. + + The string representing the Midi short message. + + + public void MyMidiProc(IntPtr handle, MIDIMessage msg, IntPtr instance, IntPtr param1, IntPtr param2) + { + if (msg == MIDIMessage.MIM_DATA) + { + // process the message... + MidiShortMessage shortMsg = new MidiShortMessage(param1, param2); + if (shortMsg.MessageType == MIDIMessageType.Channel) + Console.WriteLine(shortMsg.ToString("Time={T}: Msg={M}, Chan={C}, Status={S}, {D}")); + else if (shortMsg.MessageType == MIDIMessageType.SystemCommon) + Console.WriteLine(shortMsg.ToString("Time={T}: Msg={M}, Status={S}, {D}")); + else + Console.WriteLine(shortMsg.ToString("G")); + ... + } + ... + } + + + Public Sub MyMidiProc(handle As IntPtr, msg As MIDIMessage, instance As IntPtr, param1 As IntPtr, param2 As IntPtr) + If msg = MIDIMessage.MIM_DATA Then + ' process the message... + Dim shortMsg As New MidiShortMessage(param1, param2) + If shortMsg.MessageType = MIDIMessageType.Channel Then + Console.WriteLine(shortMsg.ToString("Time={T}: Msg={M}, Chan={C}, Status={S}, {D}")) + Else + If shortMsg.MessageType = MIDIMessageType.SystemCommon Then + Console.WriteLine(shortMsg.ToString("Time={T}: Msg={M}, Status={S}, {D}")) + Else + Console.WriteLine(shortMsg.ToString("G")) + End If + End If + ... + End If + ... + End Sub + + + + + + Returns the string representation of the Midi short message. + + The format to use (one of the following): + + "G"Combi-Format: Timestamp, Type, Channel, Status, Data in full text - same as "{T}\t{M} {C}\t{S}\t{D}" (for Channel messages) resp. "{T}\t{M}\t{S}\t{D}" (for other messages). + "g"Combi-Format: Timestamp, Type, Channel, Status, Data as numerical values - same as "{t}\t{m} {C}\t{s}\t{d}" (for Channel messages) resp. "{t}\t{m}\t{s}\t{d}" (for other messages). + "X"Combi-Format: Timespan and Message as hexadecimal values (big hex) - same as "{U} {A} {H}". + "x"Combi-Format: Timespan and Message as hexadecimal values (small hex) - same as "{u} {a} {h}". + "Y"Combi-Format: Message as hexadecimal values (big hex) - same as "{A} {H}". + "y"Combi-Format: Message as hexadecimal values (small hex) - same as "{a} {h}". + "T"Timespan only. + "t"Timestamp only. + "U"Timestamp only as hexadecimal values (big hex). + "u"Timestamp only as hexadecimal values (small hex). + "M"MessageType only in full text. + "m"MessageType as numerical values. + "S"StatusType only in full text. + "s"StatusType only as numerical value. + "A"Status only as hexadecimal values (big hex). + "a"Status only as hexadecimal values (small hex). + "C"Channel only as numerical value. + "D"Data only in full text. + "d"Data only as numerical value. + "H"Data only as hexadecimal values (big hex). + "h"Data only as hexadecimal values (small hex). + + You might also combine the single values into a full format string when enclosed in brackets (e.g. "Time={T}: Msg={M}, Chan={C}, Status={S}, Data={D}"). + In such case all the format values enclosed in brackets will be replaced by the above value representations. This allows you to format your individual message string. + + The which should be used or if the default schema values should be used. + + The string representing the Midi short message. + + + public void MyMidiProc(IntPtr handle, MIDIMessage msg, IntPtr instance, IntPtr param1, IntPtr param2) + { + if (msg == MIDIMessage.MIM_DATA) + { + // process the message... + MidiShortMessage shortMsg = new MidiShortMessage(param1, param2); + if (shortMsg.MessageType == MIDIMessageType.Channel) + Console.WriteLine(shortMsg.ToString("Time={T}: Msg={M}, Chan={C}, Status={S}, {D}")); + else if (shortMsg.MessageType == MIDIMessageType.SystemCommon) + Console.WriteLine(shortMsg.ToString("Time={T}: Msg={M}, Status={S}, {D}")); + else + Console.WriteLine(shortMsg.ToString("G")); + ... + } + ... + } + + + Public Sub MyMidiProc(handle As IntPtr, msg As MIDIMessage, instance As IntPtr, param1 As IntPtr, param2 As IntPtr) + If msg = MIDIMessage.MIM_DATA Then + ' process the message... + Dim shortMsg As New MidiShortMessage(param1, param2) + If shortMsg.MessageType = MIDIMessageType.Channel Then + Console.WriteLine(shortMsg.ToString("Time={T}: Msg={M}, Chan={C}, Status={S}, {D}")) + Else + If shortMsg.MessageType = MIDIMessageType.SystemCommon Then + Console.WriteLine(shortMsg.ToString("Time={T}: Msg={M}, Status={S}, {D}")) + Else + Console.WriteLine(shortMsg.ToString("G")) + End If + End If + ... + End If + ... + End Sub + + + + + + Gets a unique overall short message ID. + + The message ID is an internal counter which might be used to track the message order. + It will be incremented with every short-message created in the system. + So it might not be linear when using multiple devices in parallel, but it will for sure be incremental for each device, meaning each message ID generated on a device will be greater as the the previous message. + But note, that the counter will be wrapped to 0 when it reaches a value of 9,223,372,036,854,775,807. + + + + + Gets or Sets the previous short message (preceding this short message) if set (or if not set). + + + Note: Some messages might actually use two short messages (e.g. the ) to support paired values with a higher resolution (16384 instead of 128 values). + In such case two messages will be send, where one contains the the LSB value (single steps) in it's byte and the other on the MSB value (128th steps) in it's byte. + For this special case it might be useful to keep in your handler always the current and the last (previous) message. + Use this property to keep your previous message with the current short message. + To access the single value assigned to the / access the property. + You might use the , resp. the method to retrieve a combined value from two short messages resp. two data value. + Typically the messages with a of and with a value between 0 and 31 (MSB, coarse) are paired with a message of a value between 32 and 63 (LSB, fine). + But also a value of 98 (LSB, fine) will be paired with a value of 99 (MSB, coarse) as well as a value of 100 (LSB, fine) will be paired with a value of 101 (MSB, coarse). + Other pairs might be hardware specific. + If no previous message was set (e.g. see constructor overloads) this member might return . + It is also not possible to get a series of previous messages (i.e. the previous of the previous etc.) - only the last previous message is kept here. + + + + + Gets or Sets the MIDI status byte. + + + + + Gets or Sets the MIDI data byte 1. + + + + + Gets or Sets the MIDI data byte 2. + + + + + Gets the paired value (from an optional ). + + The controller value normally ranges from 0 to 127. + But if the controller is a continuous controller, this simply means that it's value can be set to any value within the range from 0 to 16383 (for 14-bit coarse/fine resolution). + To set a continuous controllers use the . By default this is never set. + In such case this property will return the combined controller value by pairing this contoller value with the one from the . + Note: You must explicitly call the method in order to obtain the paired value. + There is also no additional check performed (except that the must exist and must have a of value ). + Setting this member if will in such case also modify this short-message as well as the ! + This property should only be used when is . + Note: Some ControlChange messages might actually use two short messages (e.g. the ) to support paired values with a higher resolution (16384 instead of 128 values). + In such case two messages will be send, where one contains the the LSB value (single steps) in it's byte and the other on the MSB value (128th steps) in it's byte. + For this special case it might be useful to keep in your handler always the current and the last message. + You might use the , resp. the method to retrieve a combined value from two short messages resp. two data value. + To access the controller number using this value access the or property. + + + + + Gets or Sets the MIDI data byte 3. + + This member is only used, if the is , + for all recognized s the byte is not used and has a default value of 0! + So it is here just for completeness and will typically never be used. + + + + Gets or Sets the time that the message was received by the input device driver. The time stamp is specified as milliseconds, beginning at zero when the function was called. + + The and the members can be used in exchange and will express the same time stamp.. + + + + Gets or Sets the time that the message was received by the input device driver. The time stamp is specified in milliseconds, beginning at zero when the function was called. + + + + + Gets or Sets the time span value (typically the param2 of a Midi message). + + See for details (uses the same value as but represented as an IntPtr). + + + + Gets or Sets the constructed Midi message value. + + If a MIDI method requires an IntPtr instead on an Int32 value, please use the property. + This property will get or set all relevant bytes: , , and . + + + Sending a short message: + + // construct a message + MidiShortMessage msg = new MidiShortMessage(MIDIStatus.NoteOn, channel, note, velocity, 0, 0); + // send the message + int result = MIDI_OutShortMsg(handle, msg.Message); + + + ' construct a message + Dim msg As New MidiShortMessage(MIDIStatus.NoteOn, channel, note, velocity, 0, 0) + ' send the message + Dim result As Integer = MIDI_OutShortMsg(handle, msg.Message) + + + + + + Gets or Sets the constructed Midi message value (typically the param1 of a Midi message). + + See for details (uses the same value as but represented as an IntPtr). + + + + Gets or Sets the Midi message type (one of the values) from/to the byte. + + Here is an overview on how the messaage type is mapped evaluating the byte: + Channel Message: 0x8n - 0xEn (n = any value between 0 and F). Any NoteOff, NoteOn, Aftertouch, ControlChange, ProgramChange, ChannelPressure and PitchBend message. + SystemCommon Message: hex F0 (SystemMsgs), F1 (MidiTimeCode), F2 (SongPosition), F3 (SongSelect), F6 (TuneRequest) and F7 (EOX). + SystemRealtime Message: F8 (Clock), F9 (Tick), FA (Start), FB (Continue), FC (Stop), FE (ActiveSense) and FF (Reset). + + + + + Gets or Sets the Midi status type (one of the values) from/to the byte. + + The status type is kept in the 4 upper bits of the byte + and is also often called the type of the message (e.g. NoteOn, NoteOff, Aftertouch, ControlChange etc.). + If no usefull status type could be evaluated will be returned (which might not reflect the actual status byte value, e.g. if the has a value of 0xFD there will be no useful status type associated). + When assigning a status type the following will apply: If the new value is 0xF0 or above, the full byte will be set with the new value, else only the 4 upper bits will be set with the new value. + + + + + Gets or Sets the channel number from/to the byte. + + The channel number is kept in the 4 lower bits of the byte + and is also often just called the channel of the message (between 0 and 15). + When assigning a channel number only the lower 4-bit of the byte will be set. + This property should only be used when is . + + + + + Gets or Sets the Midi note number from/to the byte. + + The note number ranges from 0 to 127. + This property should only be used when is , or . + + + + + Gets the Midi note from the byte as a string representation. + + Exmple is: "C-1" or "DSharp0" or "A4". The latter number represents the octave (i.e. the '-1', '0' resp. '4'). + This property should only be used when is , or . + + + + + Gets or Sets the velocity (key pressure speed) from/to the byte. + + The velocity ranges from 0 to 127. + This property should only be used when is or . + + + + + Gets or Sets the polyphonic aftertouch (polyphonic key pressure) from/to the byte. + + The polyphonic aftertouch (or key pressure) ranges from 0 (no pressure) to 127 (full pressure). + This property should only be used when is . + + + + + Gets or Sets the channel pressure (channel aftertouch) from/to the byte. + + The channel pressure ranges from 0 (no pressure) to 127 (full pressure). + This property should only be used when is . + + + + + Gets or Sets the changed program number from/to the byte. + + The program change number ranges from 0 to 127. + This property should only be used when is . + If multiple banks do exist a command will select a new program number from the current bank only. + A different bank will be selected with two sub-sequent commands. This will also be called a Bank-Select-Command. + For this special case it might be useful to keep in your handler always the current and the last message. + You might use the , resp. the method to retrieve a combined value from two short messages resp. two data value. + + + + + Gets or Sets the pitch bend value from/to and as a combined value. + + The pitch bend value ranges from 0 to 16383 (128*128 values). + This property should only be used when is . + The byte will contain the LSB value (single steps) and the byte the MSB value (128th steps) both ranging from 0 to 128. + + + + + Gets or Sets the controller number from/to the byte. + + The controller number ranges from 0 to 127. + This property should only be used when is . + Note: Some ControlChange messages might actually use two short messages (e.g. the ) to support paired values with a higher resolution (16384 instead of 128 values). + In such case two messages will be send, where one contains the the LSB value (single steps) in it's byte and the other on the MSB value (128th steps) in it's byte. + For this special case it might be useful to keep in your handler always the current and the last message. + You might use the , resp. the method to retrieve a combined value from two short messages resp. two data value. + To access the single value assigned to the controler access the property. + + + + + Gets or Sets the controller type (one of the values) from/to the byte. + + + This property should only be used when is . + Note: Some ControlChange messages might actually use two short messages (e.g. the ) to support paired values with a higher resolution (16384 instead of 128 values). + In such case two messages will be send, where one contains the the LSB value (single steps) in it's byte and the other on the MSB value (128th steps) in it's byte. + For this special case it might be useful to keep in your handler always the current and the last message. + You might use the , resp. the method to retrieve a combined value from two short messages resp. two data value. + To access the single value assigned to the controler access the property. + + + + + Returns , if this short-message contains the MSB (coarse) and the the LSB (fine) value - only in case the value is set to . + + In case the value returns this property has no meaning! + + + + Returns , if the contains the MSB (coarse) and this message the LSB (fine) value - only in case the value is set to . + + In case the value returns this property has no meaning! + + + + Gets, if this message was manually set to be a continuous controller message. + + + This message is only a continuous controller message, if set via and if the exists and it's also has a value of and the is the same. + + + + + Gets or Sets the controller value from/to the byte (and optionally from the ). + + The controller value normally ranges from 0 to 127. + But if the controller is a continuous controller, this simply means that it's value can be set to any value within the range from 0 to 16383 (for 14-bit coarse/fine resolution). + To set a continuous controllers use the . By default this is never set. + In such case this property will return the combined controller value by pairing this contoller value with the one from the . + Note: You must explicitly call the method in order to obtain the paired value. + There is also no additional check performed (except that the must exist and must have a of value ). + Setting this member if will in such case also modify this short-message as well as the ! + This property should only be used when is . + Note: Some ControlChange messages might actually use two short messages (e.g. the ) to support paired values with a higher resolution (16384 instead of 128 values). + In such case two messages will be send, where one contains the the LSB value (single steps) in it's byte and the other on the MSB value (128th steps) in it's byte. + For this special case it might be useful to keep in your handler always the current and the last message. + You might use the , resp. the method to retrieve a combined value from two short messages resp. two data value. + To access the controller number using this value access the or property. + + + + + Gets or Sets the Midi Time Code type (one of the values) from/to the byte. + + + This property should only be used when is . + For more details about the Midi Time Code (MTC) representation see . + Setting this property will only modify the upper half of the byte. + + + + + Gets or Sets the Midi Time Code value (partial) from/to the byte. + + + This property should only be used when is . + For more details about the Midi Time Code (MTC) representation see . + Setting this property will only modify the lower half of the byte. + + + + + Gets or Sets the song position value from/to and as a combined value. + + The song position value ranges from 0 to 16383 (128*128 values). + Some master device that controls sequence playback sends this message to force a slave device to cue the playback to a certain point in the song/sequence. In other words, this message sets the device's "Song Position". This message doesn't actually start the playback. It just sets up the device to be "ready to play" at a particular point in the song. + This value is the also called the MIDI Beat upon which to start the song. Songs are always assumed to start on a MIDI Beat of 0. Each MIDI Beat spans 6 MIDI Clocks. In other words, each MIDI Beat is a 16th note (since there are 24 MIDI Clocks in a quarter note). + This property should only be used when is . + The byte will contain the LSB value (single steps) and the byte the MSB value (128th steps) both ranging from 0 to 128. + Example: + If a Song Position value of 8 is received, then a sequencer (or drum box) should cue playback to the third quarter note of the song. (8 MIDI beats * 6 MIDI clocks per MIDI beat = 48 MIDI Clocks. Since there are 24 MIDI Clocks in a quarter note, the first quarter occurs on a time of 0 MIDI Clocks, the second quarter note occurs upon the 24th MIDI Clock, and the third quarter note occurs on the 48th MIDI Clock). + + + + + Gets or Sets the song number from/to the byte. + + The song number ranges from 0 to 127. + This property should only be used when is . + + + + + Gets or Sets the combined , and possibly values as an integer. + + The full data value ranges from 0 to 16383 (128*128 values, default) resp. from 0 to 2097151 (128*128*128 values, in case of is ). + The byte will contain the LSB value (single steps), the byte the MSB1 value (128th steps) and the byte the MSB2 value (16384th steps) all ranging from 0 to 127. + Only in case that the is the byte will be used, since for all recognized s the byte will not be used and set to 0 (zero). + + + + + This class represents a Midi system-exclusive message as for example received in a message of a + or as being used with the and returned back in the with the message. + + You might use the class to pack (encode, construct) or unpack (decode) any Midi system-exclusive message. + System-Exclusive message use a structure as the transport vehicle between devices. Internally a data buffer needs to be prepared when sending or providing the buffer to a device. When the device finishes with the message processing you will be notified and you'll need to unprepare the buffer. + Sending system-exclusive messages to an output device: + Use this class with the method to send a message to an output device. + Beforehand use the method to construct your message buffer. You might then use the methods to write data to the data buffer. When done call the method to prepare the data buffer and make it ready to be send to the device. Once prepared the data buffer can not be changed anymore. + Finally use the property in the call to get the pointer to the constructed and prepared structure. + After sending the message make sure to capture the message in your in order to unprepare the data buffer. This is actually automatically being done within the constructor of this class when using the overload taking an IntPtr argument. + Receiving system-exclusive messages at an input device: + Use this class with the message of a to decode the received message. + Before you can receive system-exclusive messages you must constantly provide data buffers to the device (which will then be filled with data by the device and returned to your input). So you might use the method to create such empty buffer and then call to prepare the data buffer and make it ready to be send to the device. Once prepared the data buffer can not be changed anymore. + Finally use the property in the call to get the pointer to the constructed and prepared structure and provide the buffer to the device. + After providing the buffer make sure to capture the resp. message in your in order to unprepare the data buffer. This is actually automatically being done within the constructor of this class when using the overload taking an IntPtr argument. + You might use the , , etc. methods to fianlly read data from the data buffer you received and interpret it's content accordingly. + The and already handle most of these tasks (e.g. preparing and unpreparing of system-exclusive messages) for you. + + + Sending system-exclusive messages to an output device: + + private MIDIOUTPROC _midiProc; + private IntPtr _midiOutHandle; + ... + // Open the Midi device #0 + _midiProc = new MIDIOUTPROC(MyMidiOutProc); + MIDIError ret = Midi.MIDI_OutOpen(ref _midiOutHandle, 0, _midiProc, 0); + if (ret == MIDIError.MIDI_OK) + { + // output ready + } + ... + private void SendSysExBuffer(IntPtr handle, byte[] data) + { + MidiSysExMessage msg = new MidiSysExMessage(false, handle); + msg.CreateBuffer(data); + if (msg.Prepare()) + { + // if the message was perpared successfully + // send a system-exclusive message to the output device + Midi.MIDI_OutLongMsg(handle, msg.MessageAsIntPtr); + } + } + + public void MyMidiOutProc(IntPtr handle, MIDIMessage msg, IntPtr instance, IntPtr param1, IntPtr param2) + { + // handle all Midi messages here + if (msg == MIDIMessage.MOM_DONE) + { + // process the message... + // param1 will contain the pointer to the MIDI_HEADER + MidiSysExMessage sysexMsg = new MidiSysExMessage(false, handle, param1); + // the internal header is already unprepared here + // so you can still use the data... + Console.WriteLine( sysexMsg.ToString() ); + } + ... + } + + + Private _midiProc As MIDIOUTPROC + Private _midiOutHandle As IntPtr + ... + ' Open the Midi device #0 + _midiProc = New MIDIOUTPROC(AddressOf MyMidiOutProc) + Dim ret As MIDIError = Midi.MIDI_OutOpen(_midiOutHandle, 0, _midiProc, 0) + If ret = MIDIError.MIDI_OK Then + ' output ready + End If + ... + Private Sub SendSysExBuffer(handle As IntPtr, data() As Byte) + Dim msg As New MidiSysExMessage(False, handle) + msg.CreateBuffer(data) + If msg.Prepare() Then + ' if the message was perpared successfully + ' send a system-exclusive message to the output device + Midi.MIDI_OutLongMsg(handle, msg.MessageAsIntPtr) + End If + End Sub + + Public Sub MyMidiOutProc(handle As IntPtr, msg As MIDIMessage, instance As IntPtr, param1 As IntPtr, param2 As IntPtr) + ' handle all Midi messages here + If msg = MIDIMessage.MOM_DONE Then + ' process the message... + ' param1 will contain the pointer to the MIDI_HEADER + Dim sysexMsg As New MidiSysExMessage(False, handle, param1) + ' the internal header is already unprepared here + ' so you can still use the data... + Console.WriteLine(sysexMsg.ToString()) + End If + End Sub + + Receiving system-exclusive messages at an input device: + + private MIDIINPROC _midiProc; + private IntPtr _midiInHandle; + ... + // Open the Midi device #0 + _midiProc = new MIDIINPROC(MyMidiInProc); + MIDIError ret = Midi.MIDI_InOpen(ref _midiInHandle, 0, _midiProc, IntPtr.Zero, MIDIFlags.MIDI_IO_STATUS); + if (ret == MIDIError.MIDI_OK) + { + // already supply the device with 2 buffers (each 1K) + AddSysExBuffer(_midiInHandle, 1024); + AddSysExBuffer(_midiInHandle, 1024); + // Start the device + ret = Midi.MIDI_InStart(_midiInHandle); + } + ... + // prepare receiving system-exclusive messages + private void AddSysExBuffer(IntPtr handle, int size) + { + MidiSysExMessage msg = new MidiSysExMessage(true, handle); + msg.CreateBuffer(size); + if (msg.Prepare()) + { + // Add the buffer to the InputDevice. + Midi.MIDI_InAddBuffer(handle, msg.MessageAsIntPtr); + } + } + + MidiSysExMessage _sysexMsg = null; + public void MyMidiInProc(IntPtr handle, MIDIMessage msg, IntPtr instance, IntPtr param1, IntPtr param2) + { + if (msg == MIDIMessage.MIM_LONGDATA || msg == MIDIMessage.MIM_LONGERROR) + { + // process the sysex message... + // param1 will contain the pointer to the MIDI_HEADER + _sysexMsg = new MidiSysExMessage(true, handle, param1, _sysexMsg); + if (_sysexMsg.IsDone) + { + // use it... + Console.WriteLine( sysexMsg.ToString() ); + } + ... + // add a new buffer + // since we should constantly provide new buffers until we finished recording + AddSysExBuffer(handle, 1024); + } + ... + } + + + Private _midiProc As MIDIINPROC + Private _midiInHandle As IntPtr + ... + ' Open the Midi device #0 + _midiProc = New MIDIINPROC(AddressOf MyMidiInProc) + Dim ret As MIDIError = Midi.MIDI_InOpen(_midiInHandle, 0, _midiProc, IntPtr.Zero, MIDIFlags.MIDI_IO_STATUS) + If ret = MIDIError.MIDI_OK Then + ' already supply the device with 2 buffers (each 1K) + AddSysExBuffer(_midiInHandle, 1024) + AddSysExBuffer(_midiInHandle, 1024) + ' Start the device + ret = Midi.MIDI_InStart(_midiInHandle) + End If + ... + ' prepare receiving system-exclusive messages + Private Sub AddSysExBuffer(handle As IntPtr, size As Integer) + Dim msg As New MidiSysExMessage(True, handle) + msg.CreateBuffer(size) + If msg.Prepare() Then + ' Add the buffer to the InputDevice. + Midi.MIDI_InAddBuffer(handle, msg.MessageAsIntPtr) + End If + End Sub + + ' prepare sending system-exclusive messages + Dim _sysexMsg As MidiSysExMessage = Nothing + Public Sub MyMidiInProc(handle As IntPtr, msg As MIDIMessage, instance As IntPtr, param1 As IntPtr, param2 As IntPtr) + If msg = MIDIMessage.MIM_LONGDATA OrElse msg = MIDIMessage.MIM_LONGERROR Then + ' process the sysex message... + ' param1 will contain the pointer to the MIDI_HEADER + _sysexMsg = New MidiSysExMessage(True, handle, param1, _sysexMsg) + If _sysexMsg.IsDone Then + ' use it... + Console.WriteLine(sysexMsg.ToString()) + End If + ... + ' add a new buffer + ' since we should constantly provide new buffers until we finished recording + AddSysExBuffer(handle, 1024) + End If + ... + End Sub + + + + + + Creates a new and empty instance of the MidiSysExMessage. + + Dealing with a Midi input device? (=input, =output). + The handle to the MIDI device. + You might use this one together with the method to construct your own Midi system-exclusive message. + + + + Creates a new instance of the MidiSysExMessage from a pointer to a . + + Dealing with a Midi input device? (=input, =output). + The handle to the MIDI device. + A pointer to a structure to use with this system-exclusive message. + + You might use this constuctor in your or when receiving a , resp. message with the 'prarm1' value. + Calling this constructor with a valid pointer to a structure will automatically unprepare the header (using )! + However, that data of the header will first be copied to this class so it is still accessable. + The data buffer will only be set, if the flag was set - meaning the Midi device finished with the buffer. + + + + + Creates a new instance of the MidiSysExMessage from a pointer to a and also evaluates a previous system-exclusive message. + + Dealing with a Midi input device? (=input, =output). + The handle to the MIDI device. + A pointer to a structure to use with this system-exclusive message. + The previous system-exclusive message received (in order to check, if data buffers need to be concatenated). + + You might use this constuctor in your or when receiving a , resp. message with the 'prarm1' value. + This overload ensures, that sub-sequent system-exclusive messages are automatically concatenated (if needed) until the property is set to . + It might be the case, that an input device needs to use more than one system-exclusive message in order to complete one message. This because for input devices your application provide empty buffers of a given size to the device. If this buffer is not large enough to keep the full message multiple system-exclusive messages are used. + The property indicates, if the current data buffer is complete and the device driver indicates that it is finished with the buffer. + If the property is set to this would indicate, that more data is about to come and the current data buffer needs to be concatenated with sub-sequent system-exclusive messages until returns . + This overload ensures, that the current data buffer of the will automatically be appended to the data buffer of the data buffer if the previous buffer was not finished, so that this instance will contain the data buffer of the previous and this message. + If the buffer was already done or is nothing will be done and only the current data buffer will be used. + All this only applies to input devices ( should be ), since when dealing with output devices you control the amount of data to send. + Calling this constructor with a valid pointer to a structure will automatically unprepare the header (using )! + The data buffer will only be set, if the flag was set - meaning the Midi device finished with the buffer. + + + + + Creates an empty data buffer of the given size (between 2 and 65536). + + The number of byte for to buffer to use. + on success, else . + Note: The method clear all data in an existing buffer. + Calling this method on an already prepared buffer will have no effect and will be returned. + + + + Creates a data buffer with the given data buffer. + + The byte array to initialize the data buffer with. + on sucess - else will be returned (e.g. data is or it's length is less than 2). + + + + Prepares the out of the data buffer ready to be used with a device. + + on success, else . + After you have called this method the should NOT be changed! + Use the property to retrieve the prepared pointer to the which must be used to handle any system-exclusive message. + Use this property with the method to provide a data buffer to an input device in order to receive a system-exclusive message. + Use this property with the method to send a system-exclusive message to an output device. + Note: There is no 'Unprepare' method present in this class, since this will be handled automatically once you received a message back from the device and (re)create an instance of this class with the param1 IntPtr. + + + + + Prepares the out of the data buffer ready to be used with a device. + + User instance data to pass to the system-exclusive message (might be later retrieved via the property). + on success, else . + After you have called this method the should NOT be changed! + Use the property to retrieve the prepared pointer to the which must be used to handle any system-exclusive message. + Use this property with the method to provide a data buffer to an input device in order to receive a system-exclusive message. + Use this property with the method to send a system-exclusive message to an output device. + Note: There is no 'Unprepare' method present in this class, since this will be handled automatically once you received a message back from the device and (re)create an instance of this class with the param1 IntPtr. + + + + + Sends this system-exclusive message to the given . + + on success (message was send successfully), else . + Note: Before sending this system-exclusive message it must have been prepared with ! + This method will also fail, if the Midi was not opened with resp. . + If dealing with an input device () you must also start the device with . + If dealing with an input device this system-exclusive message is used to provide a buffer to the input device ( is used internally). + If dealing with an output device this system-exclusive message is send as a long message to the output device ( is used internally). + + + + + Validates the given data buffer to ensure it contains a valid system-exclusive message. + + , if the data buffer contains a valid system-exclusive message, else . + The following check is performed: + The first byte must be 0xF0 and the last byte in the buffer must be 0xF7. + The data bytes in between must all having bit #7 clear, i.e. a 0 to 127 value. + If you received a message and the property is set to it is very likely, that the message is not valid. + + + + + Returns the data buffer as a string. + + The string representation of the Midi data in the data buffer as hexadecimal values. + If no to the data buffer exists will be returned. If the is zero an empty string will be returned - + else a hexadecimal representation of the byte array of the data will be returned, e.g. "F0 41 00 ... F7". + + + + Reads an 8-bit value from the data buffer (full). + + The zero-base offset (index) of the data buffer to start reading (the offset will be automatically be increased by the number of bytes read). + The byte value (between 0 and 255) at the given position. + + + + Writes an 8-bit value to the data buffer (full). + + The zero-base offset (index) of the data buffer where to start writing (the offset will be automatically be increased by the number of bytes written). + The full byte value to write. + + You first need to initialize the data buffer with before being able to write to the buffer. + Do not call this method after you have prepared the message with , since after calling this method would have no effect. + + + + private MIDIOUTPROC _midiOutProc; + private IntPtr _midiOutHandle; + ... + _midiOutProc = new MIDIOUTPROC(MyMidiOutProc); + Midi.MIDI_OutOpen(ref _midiOutHandle, 0, _midiOutProc, 0); + ... + // create a new system-exclusive message + MidiSysExMessage sysex = new MidiSysExMessage(false, _midiOutHandle); + // message will be 8 byte (incl. SoX and EoX) + sysex.CreateBuffer(8); + // write start-of-system-exclusive + sysex.MessageWriteSoX(); + int offset = 1; + // write 6 more bytes... + sysex.MessageWrite8(ref offset, 65); + sysex.MessageWrite16(ref offset, 1023); + sysex.MessageWrite16(ref offset, 13); + sysex.MessageWrite8(ref offset, 1); + // write end-of-system-exclusive + sysex.MessageWriteEoX(); + ... + + + Private _midiOutProc As MIDIOUTPROC + Private _midiOutHandle As IntPtr + ... + _midiOutProc = New MIDIOUTPROC(AddressOf MyMidiOutProc) + Midi.MIDI_OutOpen(_midiOutHandle, 0, _midiOutProc, 0) + ... + ' create a new system-exclusive message + Dim sysex As New MidiSysExMessage(False, _midiOutHandle) + ' message will be 8 byte (incl. SoX and EoX) + sysex.CreateBuffer(8) + ' write start-of-system-exclusive + sysex.MessageWriteSoX() + Dim offset As Integer = 1 + ' write 6 more bytes... + sysex.MessageWrite8(offset, 65) + sysex.MessageWrite16(offset, 1023) + sysex.MessageWrite16(offset, 13) + sysex.MessageWrite8(offset, 1) + ' write end-of-system-exclusive + sysex.MessageWriteEoX() + + + + + + Writes the byte (0xF0) to the first byte of the data buffer. + + + You first need to initialize the data buffer with before being able to write to the buffer. + Do not call this method after you have prepared the message with , since after calling this method would have no effect. + + + + + Writes the byte (0xF7) to the last byte of the data buffer. + + + You first need to initialize the data buffer with before being able to write to the buffer. + Do not call this method after you have prepared the message with , since after calling this method would have no effect. + + + + + Reads a 7-bit value from the data buffer (right-justified). + + The zero-base offset (index) of the data buffer to start reading (the offset will be automatically be increased by the number of bytes read). + The byte value (between 0 and 127) at the given position. + + + + Writes a 7-bit value to the data buffer (right-justified). + + The zero-base offset (index) of the data buffer where to start writing (the offset will be automatically be increased by the number of bytes written). + The byte value (between 0 and 127) to write to the given position. + + You first need to initialize the data buffer with before being able to write to the buffer. + Do not call this method after you have prepared the message with , since after calling this method would have no effect. + + + + + Reads an 8-bit waveform value (2 bytes) from the data buffer (left-justified). + + The zero-base offset (index) of the data buffer to start reading (the offset will be automatically be increased by the number of bytes read). + The byte value (between 0 and 255) at the given position representing the waveform point. + + + + Writes an 8-bit waveform value (2 bytes) to the data buffer (left-justified). + + The zero-base offset (index) of the data buffer where to start writing (the offset will be automatically be increased by the number of bytes written). + The byte value (between 0 and 255) to write to the given position representing the waveform point. + + You first need to initialize the data buffer with before being able to write to the buffer. + Do not call this method after you have prepared the message with , since after calling this method would have no effect. + + + + + Reads a 14-bit value (2 bytes) from the data buffer (right-justified). + + The zero-base offset (index) of the data buffer to start reading (the offset will be automatically be increased by the number of bytes read). + The short value (between 0 and 16383) at the given position. + + + + Writes a 14-bit value (2 bytes) to the data buffer (right-justified). + + The zero-base offset (index) of the data buffer where to start writing (the offset will be automatically be increased by the number of bytes written). + The short value (between 0 and 16383) to write to the given position. + + You first need to initialize the data buffer with before being able to write to the buffer. + Do not call this method after you have prepared the message with , since after calling this method would have no effect. + + + + + Reads a 16-bit waveform value (3 bytes) from the data buffer (left-justified). + + The zero-base offset (index) of the data buffer to start reading (the offset will be automatically be increased by the number of bytes read). + The short value (between -32768 and 32767) at the given position representing the waveform point. + + + + Writes a 16-bit waveform value (3 bytes) to the data buffer (left-justified). + + The zero-base offset (index) of the data buffer where to start writing (the offset will be automatically be increased by the number of bytes written). + The short value (between -32768 and 32767) to write to the given position representing the waveform point. + + You first need to initialize the data buffer with before being able to write to the buffer. + Do not call this method after you have prepared the message with , since after calling this method would have no effect. + + + + + Reads a 21-bit value (3 bytes) from the data buffer (right-justified). + + The zero-base offset (index) of the data buffer to start reading (the offset will be automatically be increased by the number of bytes read). + The int value (between 0 and 2097152) at the given position. + + + + Writes a 21-bit value (3 bytes) to the data buffer (right-justified). + + The zero-base offset (index) of the data buffer where to start writing (the offset will be automatically be increased by the number of bytes written). + The int value (between 0 and 2097152) to write to the given position. + + You first need to initialize the data buffer with before being able to write to the buffer. + Do not call this method after you have prepared the message with , since after calling this method would have no effect. + + + + + Reads a 24-bit waveform value (4 bytes) from the data buffer (left-justified). + + The zero-base offset (index) of the data buffer to start reading (the offset will be automatically be increased by the number of bytes read). + The int value (between -8388608 and 8388607) at the given position representing the waveform point. + + + + Writes a 24-bit waveform value (4 bytes) to the data buffer (left-justified). + + The zero-base offset (index) of the data buffer where to start writing (the offset will be automatically be increased by the number of bytes written). + The int value (between -8388608 and 8388607) to write to the given position representing the waveform point. + + You first need to initialize the data buffer with before being able to write to the buffer. + Do not call this method after you have prepared the message with , since after calling this method would have no effect. + + + + + Reads a 28-bit value (4 bytes) from the data buffer (right-justified). + + The zero-base offset (index) of the data buffer to start reading (the offset will be automatically be increased by the number of bytes read). + The int value (between 0 and 268435456) at the given position. + + You first need to initialize the data buffer with before being able to write to the buffer. + Do not call this method after you have prepared the message with , since after calling this method would have no effect. + + + + + Writes a 28-bit value (4 bytes) to the data buffer (right-justified). + + The zero-base offset (index) of the data buffer where to start writing (the offset will be automatically be increased by the number of bytes written). + The int value (between 0 and 268435456) to write to the given position. + + You first need to initialize the data buffer with before being able to write to the buffer. + Do not call this method after you have prepared the message with , since after calling this method would have no effect. + + + + + Gets a unique overall short message ID. + + The message ID is an internal counter which might be used to track the message order. + It will be incremented with every short-message created in the system. + So it might not be linear when using multiple devices in parallel, but it will for sure be incremental for each device, meaning each message ID generated on a device will be greater as the the previous message. + But note, that the counter will be wrapped to 0 when it reaches a value of 9,223,372,036,854,775,807. + + + + + Dealing with a Midi input device? (=input, =output). + + + + + Gets the handle to the MIDI device. + + + + + Returns , if the data buffer is prepared and can not be changed anymore (else ). + + Once you called the method the data buffer will be prepared and sealed. It can therefore not be changed afterwards. + Use the to retrieve the prepared pointer to the structure ready to be used for sending and receiving system-exclusive messages. + + + + Gets the Midi message type (one of the values). + + Actually always returns . + + + + + Gets the prepared pointer to the structure ready to be used with a Midi device. + + + Use this property with the method to provide a data buffer to an input device in order to receive a system-exclusive message. + Use this property with the method to send a system-exclusive message to an output device. + Will return , if the data buffer is not already prepared (see ). + + + + + Gets the raw data buffer bytes representing the system-exclusive message. + + Once you called the method the data buffer will be prepared and sealed. It can therefore not be changed afterwards. + Use the property to retrieve a prepared pointer to the structure ready to be used with a Midi device. + You might use the property to check, if the data buffer is already prepared. + Use the method to check, if the data buffer contains a valid system-exclusive message. + To create a new system-exclusive message use the method to initialize the data buffer and then call the methods to write the actual data to the message data buffer. + To unpack and read a system-exclusive message use the , , etc. methods to retrieve data from the message data buffer (e.g. as received from an input device). + + + + + Gets the length of the system exclusive data buffer. + + + + + , if the data in the buffer is complete and contains all data (else ). + + This property is not mixed up with the property - which is set by the device driver to indicate that it is finished with the buffer and is returning it to the application. + Instead this property validates, if the data in the buffer represents a full system-exclusive message starting with a byte and ending with a byte. + If the member is this would indicate, that more data is about to come and this data buffer should be concatenated with sub-sequent system-exclusive messages until this flag returns . + You might use the constructor overload of this class which takes an instance of the MidiSysExMessage in order to automatically concatenate system-exclusive messages. + + + + + Gets the user instance data as passed with the method. + + + + + Gets the Midi status type (one of the values) from the first byte of the data buffer. + + The status type is kept in the first byte of the data buffer. + If no usefull status type could be evaluated will be returned (this will also be the case, if no data buffer is available). + + + + + Gets the manufacturer ID from a system-exclusive message (or -32768 if not applicable or no data buffer is present). + + The first data byte (after the ), should be a Manufacturer's ID. + Since a midi data byte can't be greater than 0x7F, that means there would only be 127 IDs to dole out to manufacturers. Well, there are more than 127 manufacturers of MIDI products. + MMA has assigned particular values of the ID byte to various manufacturers, so that a device can determine whether a SysEx message is intended for it. For example, a Roland device expects an ID byte of 0x41. If a Roland device receives a SysEx message whose ID byte isn't 0x41, then the device ignores all of the rest of the bytes up to and including the final 0xF7 which indicates that the SysEx message is finished. + To accomodate a greater range of manufacturer IDs, the MMA decided to reserve a manufacturer ID of 0 for a special purpose. When you see a manufacturer ID of 0, then there will be two more data bytes after this. These two data bytes combine to make the real manufacturer ID. So, some manufacturers have IDs that are 3 bytes, where the first byte is always 0. Using this "trick", the range of unique manufacturer IDs is extended to accomodate over 16,000 MIDI manufacturers. + For example, Microsoft's manufacturer ID consists of the 3 bytes 0x00 0x00 0x41. Note that the first byte is 0 to indicate that the real ID is 0x0041, but is still different than Roland's ID which is only the single byte of 0x41. + To accomodate this and differentiate between single-digit manufacture IDs and three digit manufacture IDs, this member will return posivive values for single-digit manufacture IDs and negavive values for all three digit manufacture IDs. + So in the above example Microsoft's ID would be returned as -65, wheres Roland's ID would be returned as 65. + There are also three special manufacturer ID reserved: , and . The later two relate to universal SysEx messages. + Note: If no manufacturer ID is actually present in the data buffer, this member might anyhow return a value, since this property simply evaluates the first data bytes after the initial . + + + + + , if the system-exclusive message contains a ID of . + + + Universal SysEx messages are SysEx messages that are not for any one particular manufacturer, but rather, meant to be utilized by all manufacturer's products. For example, many manufacturers make digital samplers. It became desirable for manufacturers to allow exchange of waveform data between each others' products. So, a standard protocol was developed called MIDI Sample Dump Standard (SDS). Of course, since waveforms typically entail large amounts of data, SysEx messages (ie, containing over a hundred bytes each) were chosen as the most suitable vehicle to transmit the data over MIDI. But, it was decided not to use a particular manufacturer's ID for these SysEx messages. So, a universal ID was created. There are actually 2 IDs dedicated to Universal SysEx messages. There's a universal ID meant for realtime messages (ie, ones that need to be responded to immediately), and one for non-realtime (ie, ones which can be processed when the device gets around to it). + No particular manufacturer is ever assigned an ID consisting of the single byte 0x7F or 0x7E. These are reserved for Universal SysEx messages adopted by the MMA. + A general template for these two IDs was defined. After the ID byte is a SysEx Channel byte. This could be from 0 to 127 for a total of 128 SysEx channels. So, although "normal" SysEx messages have no MIDI channel like Voice Category messages do, a Universal SysEx message can be sent on one of 128 SysEx channels. This allows the musician to set various devices to ignore certain Universal SysEx messages (ie, if the device allows the musician to set its Base SysEx Channel. Most devices just set their Base Sysex channel to the same number as the Base Channel for Voice Category messages). On the other hand, a SysEx channel of 127 is actually meant to tell the device to "disregard the channel and pay attention to this message regardless". + After the SysEx channel, the next two bytes are typically Sub IDs which tell what the SysEx is for. There are several Sub IDs defined for particular messages. There is a Sub ID for a Universal SysEx message to set a device's master volume. (This is different than Volume controller which sets the volume for only one particular MIDI channel). There is a Sub ID for a Universal SysEx message to set a device's Pitch Wheel bend range. There are a couple of Sub IDs for some Universal SysEx messages to implement a waveform (sample) dump over MIDI etc. + Note: This member might anyhow return a valid value, since this property simply evaluates the second data byte after the initial . + + + + + , if the system-exclusive message contains a ID of . + + + Universal SysEx messages are SysEx messages that are not for any one particular manufacturer, but rather, meant to be utilized by all manufacturer's products. For example, many manufacturers make digital samplers. It became desirable for manufacturers to allow exchange of waveform data between each others' products. So, a standard protocol was developed called MIDI Sample Dump Standard (SDS). Of course, since waveforms typically entail large amounts of data, SysEx messages (ie, containing over a hundred bytes each) were chosen as the most suitable vehicle to transmit the data over MIDI. But, it was decided not to use a particular manufacturer's ID for these SysEx messages. So, a universal ID was created. There are actually 2 IDs dedicated to Universal SysEx messages. There's a universal ID meant for realtime messages (ie, ones that need to be responded to immediately), and one for non-realtime (ie, ones which can be processed when the device gets around to it). + No particular manufacturer is ever assigned an ID consisting of the single byte 0x7F or 0x7E. These are reserved for Universal SysEx messages adopted by the MMA. + A general template for these two IDs was defined. After the ID byte is a SysEx Channel byte. This could be from 0 to 127 for a total of 128 SysEx channels. So, although "normal" SysEx messages have no MIDI channel like Voice Category messages do, a Universal SysEx message can be sent on one of 128 SysEx channels. This allows the musician to set various devices to ignore certain Universal SysEx messages (ie, if the device allows the musician to set its Base SysEx Channel. Most devices just set their Base Sysex channel to the same number as the Base Channel for Voice Category messages). On the other hand, a SysEx channel of 127 is actually meant to tell the device to "disregard the channel and pay attention to this message regardless". + After the SysEx channel, the next two bytes are Sub IDs which tell what the SysEx is for. There are several Sub IDs defined for particular messages. There is a Sub ID for a Universal SysEx message to set a device's master volume. (This is different than Volume controller which sets the volume for only one particular MIDI channel). There is a Sub ID for a Universal SysEx message to set a device's Pitch Wheel bend range. There are a couple of Sub IDs for some Universal SysEx messages to implement a waveform (sample) dump over MIDI etc. + Note: This member might anyhow return a valid value, since this property simply evaluates the second data byte after the initial . + + + + + Gets the Universal SysEx Channel number (or 255 on error or not present). + + If dealing with a Universal SysEx message the byte after the byte will typically contain a SysEx Channel number. + This could be from 0 to 127 for a total of 128 SysEx channels. So, although "normal" SysEx messages have no MIDI channel like Voice Category messages do, a Universal SysEx message can be sent on one of 128 SysEx channels. This allows the musician to set various devices to ignore certain Universal SysEx messages (ie, if the device allows the musician to set its Base SysEx Channel. Most devices just set their Base Sysex channel to the same number as the Base Channel for Voice Category messages). On the other hand, a SysEx channel of 127 is actually meant to tell the device to "disregard the channel and pay attention to this message regardless". + Note: If not dealing with a universal SysEx 255 will be returned. This member might anyhow return a valid value, since this property simply evaluates the second data byte after the initial . + + + + + Gets the Universal SysEx Sub ID (or 255 on error or not present). + + If dealing with a Universal SysEx message, the next two bytes are Sub IDs which tell what the SysEx is for. + There are several Sub IDs defined for particular messages. There is a Sub ID for a Universal SysEx message to set a device's master volume. (This is different than Volume controller which sets the volume for only one particular MIDI channel). + There is a Sub ID for a Universal SysEx message to set a device's Pitch Wheel bend range. There are a couple of Sub IDs for some Universal SysEx messages to implement a waveform (sample) dump over MIDI etc. + Note: If not dealing with a universal SysEx 255 will be returned. This member might anyhow return a valid value, since this property simply evaluates the third data byte after the initial . + + + + + Gets the Universal SysEx Sub ID (or 255 on error or not present). + + If dealing with a Universal SysEx message, the next two bytes are Sub IDs which tell what the SysEx is for. + There are several Sub IDs defined for particular messages. There is a Sub ID for a Universal SysEx message to set a device's master volume. (This is different than Volume controller which sets the volume for only one particular MIDI channel). + There is a Sub ID for a Universal SysEx message to set a device's Pitch Wheel bend range. There are a couple of Sub IDs for some Universal SysEx messages to implement a waveform (sample) dump over MIDI etc. + Note: If not dealing with a universal SysEx 255 will be returned. This member might anyhow return a valid value, since this property simply evaluates the forth data byte after the initial . + + + + + Gets the MMC Device ID (or 255 on error or not present). + + If dealing with a MIDI Machine Control (MMC) protocol the byte after the byte will contain a device ID. + Every device which can respond to MIDI Machine Control messages should have a unique (ie, individual) ID number. For example, a hard disk recorder may have an ID of 1. A MIDI sequencer controlling the hard disk recorder's record and playback may have an ID of 2. Usually, a device will allow the user to set its individual ID, so that any conflicts between devices can be resolved. The range of allowable ID numbers is 0 to 127 inclusive. By having unique ID numbers, you can use one of these ID numbers in a System Exclusive message, and then the various devices that are all daisy-chained together via MIDI can determine which device a particular System Exclusive message is meant for. Of course, even the master controller which is being used to control the entire MIDI Machine Control network can have its own, unique ID, in case slaved controllers wish to create and send messages back to the master. + NOTE: It is possible to have two (or more) devices set to the same ID number. What this means is that both devices always respond to the same MIDI Machine Control messages with that ID number, and you completely lose individual control over each. There is also no limit as to how many individual ID numbers a given device can respond to. If desired, a device can even respond to all 127 individual ID numbers, but this would be akin to a sound module that only operates in Omni mode (ie, not too useful if you have other units daisy-chained). + A channel number of 127 (referred to as the "All-Call channel number") is reserved to mean "all devices respond". When a MIDI Machine Control message with a channel nummer of 127 is sent along the MIDI bus, all devices should respond to this message if appropriate (ie, if they support the particular command of that message), regardless of their individual ID numbers. + Note: If not dealing with a universal real-time SysEx 255 will be returned. This member might anyhow return a valid value, since this property simply evaluates the second data byte after the initial . + + + + + Gets the MMC Device ID (or 255 on error or not present). + + If dealing with a MIDI Machine Control (MMC) protocol the third byte after the byte will contain the MMC command byte. + It is typically one of the following values: + + 0x01Stop + 0x02Play + 0x03Deferred Play + 0x04Fast Forward + 0x05Rewind + 0x06Record Strobe (Punch In) + 0x07Record Exit (Punch Out) + 0x09Pause + + + There are many other MMC commands existing...however you might use the , , etc. methods to read any data from the data buffer. + Note: If not dealing with a universal real-time SysEx 255 will be returned. This member might anyhow return a valid value, since this property simply evaluates the forth data byte after the initial . + + + + + This class handles all communication with a Midi input device. + + Create an instance of this class and specify a to be used. You might use the and the to enumerate all available Midi input devices (use the method to retrieve the device capabilities). + After you have called the method the is being used. However, Midi messages are not yet recorded and received. + To start recording Midi messages call the method. + It is a good idea to subscribe to the event handler before calling and . + The property might be used to supress sending certain events. + The contains a which allows you to react to all possible scenarios and to process all Midi messages and events. + Call the method to stop recording and receiving Midi message. + Once you're done with the device call to close the device and release it. + + + + using radio42.Multimedia.Midi; + ... + private MidiInputDevice _inDevice; + ... + // open and start a certain Midi input device + private void OpenAndStartDevice(int device) + { + _inDevice = new MidiInputDevice(device); + _inDevice.AutoPairController = true; + _inDevice.MessageFilter = MIDIMessageType.SystemRealtime | MIDIMessageType.SystemExclusive; + _inDevice.MessageReceived += new MidiMessageEventHandler(InDevice_MessageReceived); + if (_inDevice.Open()) + { + if (!_inDevice.Start()) + MessageBox.Show(this, "Midi device could not be started! Error: " + _inDevice.LastErrorCode.ToString(), "Midi Error"); + } + else + MessageBox.Show(this, "Midi device could not be opened! Error: " + _inDevice.LastErrorCode.ToString(), "Midi Error"); + } + + // stop and close the Midi input device + private void StopAndCloseDevice() + { + if (_inDevice != null && _inDevice.IsStarted) + { + _inDevice.Stop(); + _inDevice.Close(); + _inDevice.MessageReceived -= new MidiMessageEventHandler(InDevice_MessageReceived); + } + } + + private void InDevice_MessageReceived(object sender, MidiMessageEventArgs e) + { + if (e.IsShortMessage) + { + Console.WriteLine("{0} : {1}", e.ShortMessage.ID, e.ShortMessage.ToString()); + } + else if (e.IsSysExMessage) + { + Console.WriteLine("{0} : {1}", e.SysExMessage.ID, e.SysExMessage.ToString()); + } + else if (e.EventType == MidiMessageEventType.Opened) + { + Console.WriteLine("Midi device {0} opened.", e.DeviceID); + } + else if (e.EventType == MidiMessageEventType.Closed) + { + Console.WriteLine("Midi device {0} closed.", e.DeviceID); + } + else if (e.EventType == MidiMessageEventType.Started) + { + Console.WriteLine("Midi device {0} started.", e.DeviceID); + } + else if (e.EventType == MidiMessageEventType.Stopped) + { + Console.WriteLine("Midi device {0} stopped.", e.DeviceID); + } + } + + + Imports radio42.Multimedia.Midi + ... + Private _inDevice As MidiInputDevice + ... + ' open and start a certain Midi input device + Private Sub OpenAndStartDevice(device As Integer) + _inDevice = New MidiInputDevice(device) + _inDevice.AutoPairController = True + _inDevice.MessageFilter = MIDIMessageType.SystemRealtime Or MIDIMessageType.SystemExclusive + AddHandler _inDevice.MessageReceived, AddressOf InDevice_MessageReceived + If _inDevice.Open() Then + If Not _inDevice.Start() Then + MessageBox.Show(Me, "Midi device could not be started! Error " + _inDevice.LastErrorCode.ToString(), "Midi Error") + End If + Else + MessageBox.Show(Me, "Midi device could not be opened! Error " + _inDevice.LastErrorCode.ToString(), "Midi Error") + End If + End Sub + + ' stop and close the Midi input device + Private Sub StopAndCloseDevice() + If Not (_inDevice Is Nothing) AndAlso _inDevice.IsStarted Then + _inDevice.Stop() + _inDevice.Close() + _inDevice.MessageReceived -= New MidiMessageEventHandler(InDevice_MessageReceived) + End If + End Sub + + Private Sub InDevice_MessageReceived(sender As Object, e As MidiMessageEventArgs) + If e.IsShortMessage Then + Console.WriteLine("{0} : {1}", e.ShortMessage.ID, e.ShortMessage.ToString()) + Else + If e.IsSysExMessage Then + Console.WriteLine("{0} : {1}", e.SysExMessage.ID, e.SysExMessage.ToString()) + Else + If e.EventType = MidiMessageEventType.Opened Then + Console.WriteLine("Midi device {0} opened.", e.DeviceID) + Else + If e.EventType = MidiMessageEventType.Closed Then + Console.WriteLine("Midi device {0} closed.", e.DeviceID) + Else + If e.EventType = MidiMessageEventType.Started Then + Console.WriteLine("Midi device {0} started.", e.DeviceID) + Else + If e.EventType = MidiMessageEventType.Stopped Then + Console.WriteLine("Midi device {0} stopped.", e.DeviceID) + End If + End If + End If + End If + End If + End If + End Sub + + + + + + Creates a new instance of a MidiInputDevice. + + The input device number to use. + Use the method to open the Midi device and call to start recording messages. + To stop recording call the method. When you are done with the device you might call the method to actually close the Midi input device. + + + + + Creates a new instance of a MidiInputDevice. + + The input device number to use. + The in which all should be handled. + Use the method to open the Midi device and call to start recording messages. + To stop recording call the method. When you are done with the device you might call the method to actually close the Midi input device. + + + + + Releases all managed and unmanaged resources used by this class. + + + + + Destructor of the MidiInputDevice for finalization code. + + This destructor will run only if the method does not get called. + + + + Returns the total number of available Midi input devices. + + The number of Midi input devices present in your system. + + + + Returns all available Midi input device names. + + An array of strings representing the available devices. + + The index of the returned descriptions equals the deviceID, which might be used with the constructor of this class. + + + + + Returns all available Midi input port IDs. + + An array of int representing the available Midi port IDs. + + The values returned equals the deviceID, which might be used with the constructor of this class. + This method returns all available deviceIDs representing a Midi input port. You might use each ID with the method to retrieve the name of the respective Midi input device. + + + List all Midi input ports (devices which might be used with this class): + + int[] inPorts = MidiInputDevice.GetMidiPorts(); + foreach (int port in inPorts) + { + string name = MidiInputDevice.GetDeviceDescription(port); + Console.WriteLine("{0}={1}", port, name); + } + + + Dim inPorts As Integer() = MidiInputDevice.GetMidiPorts() + Dim port As Integer + For Each port In inPorts + Dim name As String = MidiInputDevice.GetDeviceDescription(port) + Console.WriteLine("{0}={1}", port, name) + Next port + + + + + + Returns the name of the given input device ID. + + Identifier of the MIDI input device. The device identifier varies from zero to one less than the number of devices present (see ). + The name of the Midi input device. + + + + Determines the capabilities of a specified MIDI input device. + + Identifier of the MIDI input device. The device identifier varies from zero to one less than the number of devices present. + An instance of the structure representing the device capabilities - or on error. + To determine the number of MIDI input devices present on the system, use the method. + + + + Connects this input device to a MIDI thru or output device. + + Handle to the MIDI output device or thru device. + on success, else will be returned. + After calling this function, this receives event data messages whenever a message with the same event data is sent to the output device driver. + A thru driver is a special form of MIDI output driver. The system will allow only one MIDI output device to be connected to a MIDI input device, but multiple MIDI output devices can be connected to a MIDI thru device. + Whenever this receives event data messages, a message with the same event data is sent to the given output device driver (or through the thru driver to the output drivers). + + + + + Disconnects this input device from a MIDI thru or output device. + + Handle to the MIDI output device to be disconnected. + on success, else will be returned. + Use this method to disconnect the device you connected with the method beforehand. + + + + Opens the Midi input device using the . + + on success, else . + After you have called this method the is being used. However, Midi messages are not yet recorded and received. To start recording call the method. + When you have subscribed to the event you'll get notified when the device is opened () and closed (). + Once you're done with the device call to close the device and release it. + + + Opens the Midi input device #0: + + private MidiInputDevice _inDevice; + ... + _inDevice = new MidiInputDevice(0); + _inDevice.MessageReceived += new MidiMessageEventHandler(InDevice_MessageReceived); + if (_inDevice.Open()) + { + if (!_inDevice.Start()) + MessageBox.Show(this, "Midi device could not be started! Error " + _inDevice.LastErrorCode.ToString(), "Midi Error"); + } + else + MessageBox.Show(this, "Midi device could not be opened! Error " + _inDevice.LastErrorCode.ToString(), "Midi Error"); + ... + // when done + if (_inDevice.IsStarted) + _inDevice.Stop(); + if (_inDevice.IsOpened) + _inDevice.Close(); + ... + private void InDevice_MessageReceived(object sender, MidiMessageEventArgs e) + { + if (e.IsShortMessage) + { + Console.WriteLine("{0} : {1}", e.ShortMessage.ID, e.ShortMessage.ToString()); + } + else if (e.IsSysExMessage) + { + Console.WriteLine("{0} : {1}", e.SysExMessage.ID, e.SysExMessage.ToString()); + } + } + + + Private _inDevice As MidiInputDevice + ... + _inDevice = New MidiInputDevice(0) + AddHandler _inDevice.MessageReceived, AddressOf InDevice_MessageReceived + If _inDevice.Open() Then + If Not _inDevice.Start() Then + MessageBox.Show(Me, "Midi device could not be started! Error " + _inDevice.LastErrorCode.ToString(), "Midi Error") + End If + Else + MessageBox.Show(Me, "Midi device could not be opened! Error " + _inDevice.LastErrorCode.ToString(), "Midi Error") + End If + ... + ' when done + If _inDevice.IsStarted Then + _inDevice.Stop() + End If + If _inDevice.IsOpened Then + _inDevice.Close() + End If + ... + Private Sub InDevice_MessageReceived(sender As Object, e As MidiMessageEventArgs) + If e.IsShortMessage Then + Console.WriteLine("{0} : {1}", e.ShortMessage.ID, e.ShortMessage.ToString()) + Else + If e.IsSysExMessage Then + Console.WriteLine("{0} : {1}", e.SysExMessage.ID, e.SysExMessage.ToString()) + End If + End If + End Sub + + + + + + Closes the Midi input device using the . + + on success, else . + After you have called this method the is no longer valid and released. + If the Midi Device and currently recording messages this method will also recording messages. + When you have subscribed to the event you'll get notified when the device is opened () and closed (). + After you have closed the Midi input device you might open it again using the method. + + + Opens the Midi input device #0: + + private MidiInputDevice _inDevice; + ... + _inDevice = new MidiInputDevice(0); + _inDevice.MessageReceived += new MidiMessageEventHandler(InDevice_MessageReceived); + if (_inDevice.Open()) + { + if (!_inDevice.Start()) + MessageBox.Show(this, "Midi device could not be started! Error " + _inDevice.LastErrorCode.ToString(), "Midi Error"); + } + else + MessageBox.Show(this, "Midi device could not be opened! Error " + _inDevice.LastErrorCode.ToString(), "Midi Error"); + ... + // when done + if (_inDevice.IsStarted) + _inDevice.Stop(); + if (_inDevice.IsOpened) + _inDevice.Close(); + ... + private void InDevice_MessageReceived(object sender, MidiMessageEventArgs e) + { + if (e.IsShortMessage) + { + Console.WriteLine("{0} : {1}", e.ShortMessage.ID, e.ShortMessage.ToString()); + } + else if (e.IsSysExMessage) + { + Console.WriteLine("{0} : {1}", e.SysExMessage.ID, e.SysExMessage.ToString()); + } + } + + + Private _inDevice As MidiInputDevice + ... + _inDevice = New MidiInputDevice(0) + AddHandler _inDevice.MessageReceived, AddressOf InDevice_MessageReceived + If _inDevice.Open() Then + If Not _inDevice.Start() Then + MessageBox.Show(Me, "Midi device could not be started! Error " + _inDevice.LastErrorCode.ToString(), "Midi Error") + End If + Else + MessageBox.Show(Me, "Midi device could not be opened! Error " + _inDevice.LastErrorCode.ToString(), "Midi Error") + End If + ... + ' when done + If _inDevice.IsStarted Then + _inDevice.Stop() + End If + If _inDevice.IsOpened Then + _inDevice.Close() + End If + ... + Private Sub InDevice_MessageReceived(sender As Object, e As MidiMessageEventArgs) + If e.IsShortMessage Then + Console.WriteLine("{0} : {1}", e.ShortMessage.ID, e.ShortMessage.ToString()) + Else + If e.IsSysExMessage Then + Console.WriteLine("{0} : {1}", e.SysExMessage.ID, e.SysExMessage.ToString()) + End If + End If + End Sub + + + + + + Starts recording messages from the Midi input device using the . + + on success, else . + The must have been opened to record messages. You might use the property to check this. Call to open the Midi input device. + After you have called this method the is being used, meaning it will receive any and . + When you have subscribed to the event you'll get notified when a new message was received from the Midi input device. + To stop recording messages call the method. + Once you're done with the device call to close the device and release it. + + + Opens the Midi input device #0: + + private MidiInputDevice _inDevice; + ... + _inDevice = new MidiInputDevice(0); + _inDevice.MessageReceived += new MidiMessageEventHandler(InDevice_MessageReceived); + if (_inDevice.Open()) + { + if (!_inDevice.Start()) + MessageBox.Show(this, "Midi device could not be started! Error " + _inDevice.LastErrorCode.ToString(), "Midi Error"); + } + else + MessageBox.Show(this, "Midi device could not be opened! Error " + _inDevice.LastErrorCode.ToString(), "Midi Error"); + ... + // when done + if (_inDevice.IsStarted) + _inDevice.Stop(); + if (_inDevice.IsOpened) + _inDevice.Close(); + ... + private void InDevice_MessageReceived(object sender, MidiMessageEventArgs e) + { + if (e.IsShortMessage) + { + Console.WriteLine("{0} : {1}", e.ShortMessage.ID, e.ShortMessage.ToString()); + } + else if (e.IsSysExMessage) + { + Console.WriteLine("{0} : {1}", e.SysExMessage.ID, e.SysExMessage.ToString()); + } + } + + + Private _inDevice As MidiInputDevice + ... + _inDevice = New MidiInputDevice(0) + AddHandler _inDevice.MessageReceived, AddressOf InDevice_MessageReceived + If _inDevice.Open() Then + If Not _inDevice.Start() Then + MessageBox.Show(Me, "Midi device could not be started! Error " + _inDevice.LastErrorCode.ToString(), "Midi Error") + End If + Else + MessageBox.Show(Me, "Midi device could not be opened! Error " + _inDevice.LastErrorCode.ToString(), "Midi Error") + End If + ... + ' when done + If _inDevice.IsStarted Then + _inDevice.Stop() + End If + If _inDevice.IsOpened Then + _inDevice.Close() + End If + ... + Private Sub InDevice_MessageReceived(sender As Object, e As MidiMessageEventArgs) + If e.IsShortMessage Then + Console.WriteLine("{0} : {1}", e.ShortMessage.ID, e.ShortMessage.ToString()) + Else + If e.IsSysExMessage Then + Console.WriteLine("{0} : {1}", e.SysExMessage.ID, e.SysExMessage.ToString()) + End If + End If + End Sub + + + + + + Stops recording messages from the Midi input device using the . + + on success, else . + The must have been opened and started to record messages. You might use the and properties to check this. Call to open the Midi input device and to start recording messages. + After you have called this method the is no longer recording and receiving any or . + When you have subscribed to the event you'll get notified when a new message was received from the Midi input device. + To start recording messages again call the method. + Once you're done with the device call to close the device and release it. + + + Opens the Midi input device #0: + + private MidiInputDevice _inDevice; + ... + _inDevice = new MidiInputDevice(0); + _inDevice.MessageReceived += new MidiMessageEventHandler(InDevice_MessageReceived); + if (_inDevice.Open()) + { + if (!_inDevice.Start()) + MessageBox.Show(this, "Midi device could not be started! Error " + _inDevice.LastErrorCode.ToString(), "Midi Error"); + } + else + MessageBox.Show(this, "Midi device could not be opened! Error " + _inDevice.LastErrorCode.ToString(), "Midi Error"); + ... + // when done + if (_inDevice.IsStarted) + _inDevice.Stop(); + if (_inDevice.IsOpened) + _inDevice.Close(); + ... + private void InDevice_MessageReceived(object sender, MidiMessageEventArgs e) + { + if (e.IsShortMessage) + { + Console.WriteLine("{0} : {1}", e.ShortMessage.ID, e.ShortMessage.ToString()); + } + else if (e.IsSysExMessage) + { + Console.WriteLine("{0} : {1}", e.SysExMessage.ID, e.SysExMessage.ToString()); + } + } + + + Private _inDevice As MidiInputDevice + ... + _inDevice = New MidiInputDevice(0) + AddHandler _inDevice.MessageReceived, AddressOf InDevice_MessageReceived + If _inDevice.Open() Then + If Not _inDevice.Start() Then + MessageBox.Show(Me, "Midi device could not be started! Error " + _inDevice.LastErrorCode.ToString(), "Midi Error") + End If + Else + MessageBox.Show(Me, "Midi device could not be opened! Error " + _inDevice.LastErrorCode.ToString(), "Midi Error") + End If + ... + ' when done + If _inDevice.IsStarted Then + _inDevice.Stop() + End If + If _inDevice.IsOpened Then + _inDevice.Close() + End If + ... + Private Sub InDevice_MessageReceived(sender As Object, e As MidiMessageEventArgs) + If e.IsShortMessage Then + Console.WriteLine("{0} : {1}", e.ShortMessage.ID, e.ShortMessage.ToString()) + Else + If e.IsSysExMessage Then + Console.WriteLine("{0} : {1}", e.SysExMessage.ID, e.SysExMessage.ToString()) + End If + End If + End Sub + + + + + + Creates and adds a system exclusive buffer to the midi device. + + For internal use only - not to be used directly in your application. + + + + Is the given a paired controller message? + + The to check. + + 0 = not a pair; + -1 = this is the first one, needs to be stacked; + +1 = this is the second one, need to be flushed (thisIsMSB); + +2 = this is the second one, need to be flushed (previousIsMSB) + + + + + Event handler used to notify that the input device has received a message or the status has changed. + + It is a good idea to subscribe to this event handler before calling and . + The property might be used to supress sending certain events. + The contains a which allows you to react to all possible scenarios and to process all these events. + Note: This implementation ensures, that the event will be executed in the main thread the subscriber executes in! + So when subscribing to this event from UI thread, the specified event delegate will also be called in that UI thread. + + + + + Returns , if this class is being disposed. + + + + + Returns the device handle for this input device. + + + + + Returns the device id (number) which was used to create this instance. + + + + + Gets or Sets the maximum buffer size for system-exclusive messages (between 2 and 65536, default is 1024). + + + + + User instance data to be used when providing system-exclusive messages. + + This member will be provided back in the received . + + + + Gets the current (last) which was received from the . + + + Might return , if no message was received so far (this class must at least have received one Midi short messages before this member returns a valid message). + You might use the member of this property to access the previous short message received etc. + + + + + Gets the current (last) which was received from the . + + + Might return , if no system-exclusive message was received so far (this class must at least have received one Midi system-exclusive messages before this member returns a valid message). + + + + + Returns if the Midi input device is opened - else . + + To open the Midi input device call the method. Use the method to start recording messages from the if it is opened and use to stop recording from the device. + When you are done with the Midi input device you might call to actually close the device. + Any as well as any event will only be received between start and stop. + + + + + Returns if the Midi input device is started and recording messages - else . + + To open the Midi input device call the method. Use the method to start recording messages from the and use to stop recording from the device. + When you are done with the Midi input device you might call to actually close the device. + Any as well as any event will only be received between start and stop. + + + + + Returns the last Midi error code (see for possible values). + + + + + Gets or Sets if Channel Messages (a ) with a should automatically be paired (default is None). + + + Some controllers are continuous controllers, which simply means that their value can be set to any value within the range from 0 to 16383 (for 14-bit coarse/fine resolution) or 0 to 127 (for 7-bit, coarse resolution). + Setting this property to will automatically pair short-message values defined in the . + In such case only one event will be fired, containing the combined (paired, 14-bit) . + In detail: Some Midi data messages might actually use two sub-sequent short messages to construct a paired message representing a single value range (e.g. the with a ). + This to support paired values with a higher resolution (16384 instead of 128 values). + In such case normally two short messages will be send, where one contains the LSB value (single steps, fine) in it's byte and the other message contains the MSB value (128th steps, coarse) in it's byte. + Typically the messages with a of and with a value between 0 and 31 (MSB, coarse) are paired with a message of a value between 32 and 63 (LSB, fine). + But also a value of 98 (LSB, fine) will be paired with a value of 99 (MSB, coarse) as well as a value of 100 (LSB, fine) will be paired with a value of 101 (MSB, coarse). + Other pairs might be hardware specific and might be specified by using the . + The resulting combined data value will be constructed like this: dataMSB=0xxxxxxx, dataLSB=0yyyyyyy = paired=00xxxxxxxyyyyyyy. + By default this property is set to meaning each individual short message will be handled and independently as a single message. + If this member is set to and the message is a ControlChange message and is defined in the , then only the second message will fire the event. + In case the Midi device will under certain cases not send paired messages together the non-paired message will be handled as a single message again. + For example: It's only desirable to make fine adjustments to the Mod Wheel without changing its current coarse setting (or vice versa), a device can be sent only a controller #33 message without a preceding controller #1 message (or vice versa). + Thus, if a device can respond to both coarse and fine adjustments for a particular controller (ie, implements the full 14-bit resolution), it should be able to deal with either the coarse or fine controller message being sent without its counterpart following. + The same holds true for other continuous (ie, coarse/fine pairs of) controllers. + In any case you can simply access the property and you'll get in return the combined and paired 14-bit controller value or the single uncombined value without further taking care. + Use the to define the controller pairs belonging together and for more details. + NOTE: ControlChannel messages are ONLY combined and paired if the messages as defined in the are send exactly subsequently (with no other short-message in between)! + + + + + Sets the controller pair matrix to automatic combine any with a of . + + + Some controllers are continuous controllers, which simply means that their value can be set to any value within the range from 0 to 16383 (for 14-bit coarse/fine resolution) or 0 to 127 (for 7-bit, coarse resolution). + Some Midi data messages might actually use two sub-sequent short messages to construct a paired message representing a single value range (e.g. the with a ). + This to support paired values with a higher resolution (16384 instead of 128 values). + This matrix defines how sub-sequent short-messages with a of are detected and which controller number defines the MSB (coarse) value and which defines the LSB (fine) value. + Furthermore the matrix defines which controller number is used in the single combined and paired short-message used in the resulting event. + When a continuous controller pair is detected (see ) by default only the last received short-message of the pair will be used when raising the event. + If the Midi input device follows the general rule and first sends the MSB (coarse) controller message and right after the LSB (fine) controller message this would mean, that in the event handle you would only see the last LSB (fine) message (the previous message with the MSB, coarse value will always be suppressed). + However, when accessing the of the fired message you will receive the combined and paired 14-bit conroller value between 0 and 16383. + Sometimes Midi devices do not send the paired messages in a particular order. This would mean that controller pairs can still be detected and combined, but that in such case still the last received short-message of the pair will be used when the event is raised. + This would result in the fact, that your application would sometimes receive the LSB short-message and sometimes the MSB short-message (see ). + To handle this circumstance the ColtrollerPairMatrix keeps a value allowing you to swap or redefine the value being used with the fired with the event. + NOTE: This property is only evaluated, if the property is set to and the ControlChannel messages are send exactly subsequently (with no other short-message in between)! + So how is the ColtrollerPairMatrix defined: + The matrix is defined as a two dimentional byte array meaning each element of the first dimention consists of 3 elements. Whereas the first dimention is simply the list of all defined controller pairs. + The matrix layout: + + VerticalThe list of defined controller pairs (each entry represents a controller pair to be combined). + HorizontalThe definition of each controller pair: + First value : the MSB (coarse) controller number (see ). + Second value: the LSB (fine) controller number (see ). + Third value : the swap flag for the of the forwarded message: + + 255Leave current and previous message as is. + 254Use the LSB message value, swap previous message if needed. + 253Use the MSB message value, swap previous message if needed. + 252Use the LSB message value, leave previous message as is. + 251Use the MSB message value, leave previous message as is. + <128Overwrite and use this value, leave previous message as is. + + + + + + --MSB-LSB--SWAP-> (definition) + | 0, 32, 255 + | 1, 33, 255 + | 2, 34, 255 + | ... ... ... + | 99, 98, 254 + | 101, 100, 254 + v + (Pairs) + + + + Here is the default definition of this property: + + byte[,] ColtrollerPairMatrix = new byte[34,3] + { + { 0, 32, 255}, + { 1, 33, 255}, + { 2, 34, 255}, + { 3, 35, 255}, + { 4, 36, 255}, + { 5, 37, 255}, + { 6, 38, 255}, + { 7, 39, 255}, + { 8, 40, 255}, + { 9, 41, 255}, + { 10, 42, 255}, + { 11, 43, 255}, + { 12, 44, 255}, + { 13, 45, 255}, + { 14, 46, 255}, + { 15, 47, 255}, + { 16, 48, 255}, + { 17, 49, 255}, + { 18, 50, 255}, + { 19, 51, 255}, + { 20, 52, 255}, + { 21, 53, 255}, + { 22, 54, 255}, + { 23, 55, 255}, + { 24, 56, 255}, + { 25, 57, 255}, + { 26, 58, 255}, + { 27, 59, 255}, + { 28, 60, 255}, + { 29, 61, 255}, + { 30, 62, 255}, + { 31, 63, 255}, + { 99, 98, 255}, + {101, 100, 255} + }; + + + You might use the and properties to identify which message contains the coarse (MSB) or fine (LSB) controller value. + A access the paired short-message use the member. + + + + private MidiInputDevice _inDevice = null; + ... + _inDevice = new MidiInputDevice(0); + _inDevice.AutoPairController = true; + _inDevice.MessageReceived += new MidiMessageEventHandler(InDevice_MessageReceived); + if ( _inDevice.Open() ) + _inDevice.Start(); + ... + private void InDevice_MessageReceived(object sender, MidiMessageEventArgs e) + { + if (e.IsShortMessage) + { + if (e.ShortMessage.IsSetAsContinuousController) + { + Console.WriteLine("Continuous Controller {0}: Value={1}", + e.ShortMessage.Controller, + e.ShortMessage.ControllerValue); + Console.WriteLine("MSB ControllerType={0}, LSB ControllerType={1}", + e.ShortMessage.ThisIsMSB ? e.ShortMessage.ControllerType : + e.ShortMessage.PreviousShortMessage.ControllerType, + e.ShortMessage.PreviousIsMSB ? e.ShortMessage.ControllerType : + e.ShortMessage.PreviousShortMessage.ControllerType); + } + else + Console.WriteLine(e.ShortMessage.ToString()); + } + ... + } + + + Private _inDevice As MidiInputDevice = Nothing + ... + _inDevice = New MidiInputDevice(0) + _inDevice.AutoPairController = True + AddHandler _inDevice.MessageReceived, AddressOf InDevice_MessageReceived + If _inDevice.Open() Then + _inDevice.Start() + End If + ... + Private Sub InDevice_MessageReceived(sender As Object, e As MidiMessageEventArgs) + If e.IsShortMessage Then + If e.ShortMessage.IsSetAsContinuousController Then + Console.WriteLine("Continuous Controller {0}: Value={1}", + e.ShortMessage.Controller, + e.ShortMessage.ControllerValue) + If e.ShortMessage.ThisIsMSB Then + Console.WriteLine("MSB ControllerType={0}", e.ShortMessage.ControllerType) + Else + Console.WriteLine("MSB ControllerType={0}", e.ShortMessage.PreviousShortMessage.ControllerType) + End If + If e.ShortMessage.PreviousIsMSB Then + Console.WriteLine("LSB ControllerType={0}", e.ShortMessage.ControllerType) + Else + Console.WriteLine("LSB ControllerType={0}", e.ShortMessage.PreviousShortMessage.ControllerType) + End If + Else + Console.WriteLine(e.ShortMessage.ToString()) + End If + End If + End Sub + + + + + + Gets or Sets the filter to be applied (messages types which should be suppressed). + + By default all messages will raise the event. + You might combine any value of the enumeration in order to supresses certain messages (e.g. to not process real-time messages). + + + Supress all real-time and system-exclusive messages: + + private MidiInputDevice _inDevice = null; + ... + _inDevice = new MidiInputDevice(0); + _inDevice.AutoPairController = true; + _inDevice.MessageFilter = MIDIMessageType.SystemRealtime | MIDIMessageType.SystemExclusive; + _inDevice.MessageReceived += new MidiMessageEventHandler(InDevice_MessageReceived); + if ( _inDevice.Open() ) + _inDevice.Start(); + ... + + + Private _inDevice As MidiInputDevice = Nothing + ... + _inDevice = New MidiInputDevice(0) + _inDevice.AutoPairController = True + _inDevice.MessageFilter = MIDIMessageType.SystemRealtime Or MIDIMessageType.SystemExclusive + AddHandler _inDevice.MessageReceived, AddressOf InDevice_MessageReceived + If _inDevice.Open() Then + _inDevice.Start() + End If + + + + + + Gets or Sets if erroneous Midi messages should also be processed. + + + Sometimes a Midi device might send invalid or erroneous Midi messages. + This property defines, if erroneous Midi messages (see and ) + should anyhow be used and raise the event. + If set to (default) only valid messages will be processed. + + + + + This class handles all communication with a Midi output device. + + Create an instance of this class and specify a to be used. You might use the and the to enumerate all available Midi output devices (use the method to retrieve the device capabilities). + After you have called the method the is being used. + It is a good idea to subscribe to the event handler before calling . However, this is generally not needed, since a for an output device there not many events being received (beside that the device is opened and closed and that the Midi output device has finished with a system-exclusive message). + The contains a which allows you to react to all possible scenarios and to process all Midi messages and events. + To send any short or system-exclusive message use one of the overloads. You might use the resp. the class in order to construct any message to be send. + Once you're done with the device call to close the device and release it. + + + + using radio42.Multimedia.Midi; + ... + private MidiOutputDevice _outDevice; + ... + // open a certain Midi output device + private void OpenDevice(int device) + { + _outDevice = new MidiOutputDevice(device); + if (!_outDevice.Open()) + MessageBox.Show(this, "Midi device could not be opened! Error " + _outDevice.LastErrorCode.ToString(), "Midi Error"); + } + } + + // close the Midi output device + private void StopAndCloseDevice() + { + if (_outDevice != null && _outDevice.IsOpened) + { + _outDevice.Close(); + } + } + ... + // create and send a new short message to the output device + MidiShortMessage msg = new MidiShortMessage(MIDIStatus.NoteOn, 0, 64, 65, 0); + if ( _outDevice.Send(msg) ) + Console.WriteLine("Error sending short message!"); + ... + // create a new system-exclusive message for the output device + MidiSysExMessage sysex = new MidiSysExMessage(false, _outDevice.Device); + sysex.CreateBuffer( new byte[7] {0xF0, 0x43, 0x75, 0x73, 0x12, 0x00, 0xF7} ); + // send it + if ( _outDevice.Send(sysex) ) + Console.WriteLine("Error sending system-exclusive message!"); + ... + + + Imports radio42.Multimedia.Midi + ... + Private _outDevice As MidiOutputDevice + ... + ' open a certain Midi output device + Private Sub OpenDevice(device As Integer) + _outDevice = New MidiOutputDevice(device) + If Not _outDevice.Open() Then + MessageBox.Show(Me, "Midi device could not be opened! Error " + _outDevice.LastErrorCode.ToString(), "Midi Error") + End If + End Sub + + ' close the Midi output device + Private Sub StopAndCloseDevice() + If Not (_outDevice Is Nothing) AndAlso _outDevice.IsOpened Then + _outDevice.Close() + End If + End Sub + ... + ' create and send a new short message to the output device + Dim msg As New MidiShortMessage(MIDIStatus.NoteOn, 0, 64, 65, 0) + If _outDevice.Send(msg) Then + Console.WriteLine("Error sending short message!") + End If + ... + ' create a new system-exclusive message for the output device + Dim sysex As New MidiSysExMessage(False, _outDevice.Device) + sysex.CreateBuffer(New Byte(7) {&HF0, &H43, &H75, &H73, &H12, &H0, &HF7}) + ' send it + If _outDevice.Send(sysex) Then + Console.WriteLine("Error sending system-exclusive message!") + End If + + + + + + Creates a new instance of a MidiOutputDevice. + + The output device number to use. + Use the method to open the Midi device. + With the methods you can send any message to the output device. + When you are done with the device you might call the method to actually close the Midi output device. + + + + + Releases all managed and unmanaged resources used by this class. + + + + + Destructor of the MidiOutputDevice for finalization code. + + This destructor will run only if the method does not get called. + + + + Returns the total number of available Midi output devices. + + The number of Midi output devices present in your system. + + + + Returns all available Midi output device names. + + An array of strings representing the available devices. + + The index of the returned descriptions equals the deviceID, which might be used with the constructor of this class. + Note: Not all Midi output devices might used when sending messages. So you should check the device capabilities (see - typically only Midi output devices with the property set to should be used with this class). + + + + + Returns all available Midi output port IDs. + + An array of int representing the available Midi port IDs. + + The values returned equals the deviceID, which might be used with the constructor of this class. + This method returns all available deviceIDs representing a Midi output port. You might use each ID with the method to retrieve the name of the respective Midi output device. + + + List all Midi output ports (devices which might be used with this class): + + int[] outPorts = MidiOutputDevice.GetMidiPorts(); + foreach (int port in outPorts) + { + string name = MidiOutputDevice.GetDeviceDescription(port); + Console.WriteLine("{0}={1}", port, name); + } + + + Dim outPorts As Integer() = MidiOutputDevice.GetMidiPorts() + Dim port As Integer + For Each port In outPorts + Dim name As String = MidiOutputDevice.GetDeviceDescription(port) + Console.WriteLine("{0}={1}", port, name) + Next port + + + + + + Returns the name of the given output device ID. + + Identifier of the MIDI output device. The device identifier varies from zero to one less than the number of devices present (see ). + The name of the Midi output device. + + + + Determines the capabilities of a specified MIDI output device. + + Identifier of the MIDI output device. The device identifier varies from zero to one less than the number of devices present. + An instance of the structure representing the device capabilities - or on error. + To determine the number of MIDI output devices present on the system, use the method. + + + + Connects this output device (must actually be a MIDI thru device) to a MIDI output device. + + Handle to the MIDI output device. + on success, else will be returned. + After calling this function, this receives event data messages whenever a message with the same event data is sent to the output device driver. + A thru driver is a special form of MIDI output driver. The system will allow only one MIDI output device to be connected to a MIDI input device, but multiple MIDI output devices can be connected to a MIDI thru device. + Whenever this receives event data messages, a message with the same event data is sent to the given output device driver (or through the thru driver to the output drivers). + + + + + Disconnects this output device (must actually be a MIDI thru device) from a MIDI output device. + + Handle to the MIDI output device to be disconnected. + on success, else will be returned. + Use this method to disconnect the device you connected with the method beforehand. + + + + Opens the Midi output device using the . + + on success, else . + After you have called this method the is being used and you might send messages to the device using the methods. + When you have subscribed to the event you'll get notified when the device is opened () and closed (). + Once you're done with the device call to close the device and release it. + + + + private MidiOutputDevice _outDevice; + ... + _outDevice = new MidiOutputDevice(0); + _outDevice.MessageReceived += new MidiMessageEventHandler(OutDevice_MessageReceived); + if (!_outDevice.Open()) + { + MessageBox.Show(this, "Midi device could not be opened! Error " + _outDevice.LastErrorCode.ToString(), "Midi Error"); + } + ... + // when done + if (_outDevice.IsOpened) + _outDevice.Close(); + ... + private void OutDevice_MessageReceived(object sender, MidiMessageEventArgs e) + { + if (e.EventType == MidiMessageEventType.Opened) + { + Console.WriteLine("Midi device {0} opened.", e.DeviceID); + } + else if (e.EventType == MidiMessageEventType.Closed) + { + Console.WriteLine("Midi device {0} closed.", e.DeviceID); + } + } + + + Private _outDevice As MidiOutputDevice + ... + _outDevice = New MidiOutputDevice(0) + AddHandler _outDevice.MessageReceived, AddressOf OutDevice_MessageReceived + If Not _outDevice.Open() Then + MessageBox.Show(Me, "Midi device could not be opened! Error " + _outDevice.LastErrorCode.ToString(), "Midi Error") + End If + ... + ' when done + If _outDevice.IsOpened Then + _outDevice.Close() + End If + ... + Private Sub OutDevice_MessageReceived(sender As Object, e As MidiMessageEventArgs) + If e.EventType = MidiMessageEventType.Opened Then + Console.WriteLine("Midi device {0} opened.", e.DeviceID) + Else + If e.EventType = MidiMessageEventType.Closed Then + Console.WriteLine("Midi device {0} closed.", e.DeviceID) + End If + End If + End Sub + + + + + + Closes the Midi output device using the . + + on success, else . + After you have called this method the is no longer valid and released. + When you have subscribed to the event you'll get notified when the device is opened () and closed (). + After you have closed the Midi output device you might open it again using the method. + + + + private MidiOutputDevice _outDevice; + ... + _outDevice = new MidiOutputDevice(0); + _outDevice.MessageReceived += new MidiMessageEventHandler(OutDevice_MessageReceived); + if (!_outDevice.Open()) + { + MessageBox.Show(this, "Midi device could not be opened! Error " + _outDevice.LastErrorCode.ToString(), "Midi Error"); + } + ... + // when done + if (_outDevice.IsOpened) + _outDevice.Close(); + ... + private void OutDevice_MessageReceived(object sender, MidiMessageEventArgs e) + { + if (e.EventType == MidiMessageEventType.Opened) + { + Console.WriteLine("Midi device {0} opened.", e.DeviceID); + } + else if (e.EventType == MidiMessageEventType.Closed) + { + Console.WriteLine("Midi device {0} closed.", e.DeviceID); + } + } + + + Private _outDevice As MidiOutputDevice + ... + _outDevice = New MidiOutputDevice(0) + AddHandler _outDevice.MessageReceived, AddressOf OutDevice_MessageReceived + If Not _outDevice.Open() Then + MessageBox.Show(Me, "Midi device could not be opened! Error " + _outDevice.LastErrorCode.ToString(), "Midi Error") + End If + ... + ' when done + If _outDevice.IsOpened Then + _outDevice.Close() + End If + ... + Private Sub OutDevice_MessageReceived(sender As Object, e As MidiMessageEventArgs) + If e.EventType = MidiMessageEventType.Opened Then + Console.WriteLine("Midi device {0} opened.", e.DeviceID) + Else + If e.EventType = MidiMessageEventType.Closed Then + Console.WriteLine("Midi device {0} closed.", e.DeviceID) + End If + End If + End Sub + + + + + + Sends a short message to the output . + + The instance of the to send. + on success, else (see for details). + + The must have been opened with the method (or check ) before sending any message. + + + + private MidiOutputDevice _outDevice = null; + ... + _outDevice = new MidiOutputDevice(0); + if (!_outDevice.Open()) + Console.WriteLine( "Could not open Midi device!" ); + + // create and send a new short message to the output device + MidiShortMessage msg = new MidiShortMessage(MIDIStatus.NoteOn, 0, 64, 65, 0); + if (_outDevice.Send(msg)) + Console.WriteLine("Error sending short message!"); + + + private MidiOutputDevice _outDevice = null; + ... + _outDevice = New MidiOutputDevice(0) + If Not _outDevice.Open() Then + Console.WriteLine("Could not open Midi device!") + End If + + ' create and send a new short message to the output device + Dim msg As New MidiShortMessage(MIDIStatus.NoteOn, 0, 64, 65, 0) + If _outDevice.Send(msg) Then + Console.WriteLine("Error sending short message!") + End If + + + + + + Sends a short message to the output . + + The short message value to use. + on success, else (see for details). + + The must have been opened with the method (or check ) before sending any message. + + + + private MidiOutputDevice _outDevice = null; + ... + _outDevice = new MidiOutputDevice(0); + if ( !_outDevice.Open() ) + Console.WriteLine( "Could not open Midi device!" ); + + // send a new short message to the output device + if ( _outDevice.Send(0x414090) ) + Console.WriteLine("Error sending short message!"); + + + private MidiOutputDevice _outDevice = null; + ... + _outDevice = New MidiOutputDevice(0) + If Not _outDevice.Open() Then + Console.WriteLine("Could not open Midi device!") + End If + + ' send a new short message to the output device + If _outDevice.Send(&H414090) Then + Console.WriteLine("Error sending short message!") + End If + + + + + + Sends a short message to the output . + + The to use to construct the short message. + The channel number to use to construct the short message (will be combined with the in lower 4-bits). + The Data1 value to use to construct the short message. + The Data2 value to use to construct the short message. + on success, else (see for details). + + The must have been opened with the method (or check ) before sending any message. + + + + private MidiOutputDevice _outDevice = null; + ... + _outDevice = new MidiOutputDevice(0); + if ( !_outDevice.Open() ) + Console.WriteLine("Could not open Midi device!"); + + // send a new short message to the output device + if ( _outDevice.Send((byte)MIDIStatus.NoteOn, 1, 64, 65) ) + Console.WriteLine("Error sending short message!"); + + + private MidiOutputDevice _outDevice = null; + ... + _outDevice = New MidiOutputDevice(0) + If Not _outDevice.Open() Then + Console.WriteLine("Could not open Midi device!") + End If + + ' send a new short message to the output device + If _outDevice.Send(CByte(MIDIStatus.NoteOn), 1, 64, 65) Then + Console.WriteLine("Error sending short message!") + End If + + + + + + Sends a short message to the output . + + The to use to construct the short message. + The Data1 value to use to construct the short message. + The Data2 value to use to construct the short message. + on success, else (see for details). + + The must have been opened with the method (or check ) before sending any message. + + + + private MidiOutputDevice _outDevice = null; + ... + _outDevice = new MidiOutputDevice(0); + if ( !_outDevice.Open() ) + Console.WriteLine("Could not open Midi device!"); + + // send a new short message to the output device + if ( _outDevice.Send(0x90, 40, 41) ) + Console.WriteLine("Error sending short message!"); + + + private MidiOutputDevice _outDevice = null; + ... + _outDevice = New MidiOutputDevice(0) + If Not _outDevice.Open() Then + Console.WriteLine("Could not open Midi device!") + End If + + ' send a new short message to the output device + If _outDevice.Send(&H90, 40, 41) Then + Console.WriteLine("Error sending short message!") + End If + + + + + + Sends a system-exclusive message to the output . + + The unprepared instance of the to send. + on success, else (see for details). + The must be created for this output and must be unprepared (meaning the method should not have been called yet, since this will be handled inside this method). + If you created the system-exclusive message for a different this method will return . + The must have been opened with the method (or check ) before sending any message. + + + + private MidiOutputDevice _outDevice = null; + ... + _outDevice = new MidiOutputDevice(0); + if ( !_outDevice.Open() ) + Console.WriteLine("Could not open Midi device!"); + + // create a new system-exclusive message for the output device + MidiSysExMessage sysex = new MidiSysExMessage(false, _outDevice.Device); + sysex.CreateBuffer(new byte[7] {0xF0, 0x43, 0x75, 0x73, 0x12, 0x00, 0xF7}); + // send it + if ( _outDevice.Send(sysex) ) + Console.WriteLine("Error sending system-exclusive message!"); + + + private MidiOutputDevice _outDevice = null; + ... + _outDevice = New MidiOutputDevice(0) + If Not _outDevice.Open() Then + Console.WriteLine("Could not open Midi device!") + End If + + ' create a new system-exclusive message for the output device + Dim sysex As New MidiSysExMessage(False, _outDevice.Device) + sysex.CreateBuffer(New Byte(7) {&HF0, &H43, &H75, &H73, &H12, &H0, &HF7}) + ' send it + If _outDevice.Send(sysex) Then + Console.WriteLine("Error sending system-exclusive message!") + End If + + + + + + Sends a system-exclusive message to the output . + + The byte array containing system-exclusive message data buffer to send. + on success, else (see for details). + The byte array should normally start with 0xF0 and end with 0xF7 - however, no validity check is performed on this. + The must have been opened with the method (or check ) before sending any message. + + + + private MidiOutputDevice _outDevice = null; + ... + _outDevice = new MidiOutputDevice(0); + if ( !_outDevice.Open() ) + Console.WriteLine( "Could not open Midi device!" ); + + // send a new system-exclusive message to the output device + if (_outDevice.Send(new byte[7] {0xF0, 0x43, 0x75, 0x73, 0x12, 0x00, 0xF7})) + Console.WriteLine("Error sending system-exclusive message!"); + + + private MidiOutputDevice _outDevice = null; + ... + _outDevice = New MidiOutputDevice(0) + If Not _outDevice.Open() Then + Console.WriteLine("Could not open Midi device!") + End If + + ' send a new system-exclusive message to the output device + If _outDevice.Send(New Byte(7) {&HF0, &H43, &H75, &H73, &H12, &H0, &HF7}) Then + Console.WriteLine("Error sending system-exclusive message!") + End If + + + + + + Event handler used to notify that the output device has processed a message or the status has changed. + + It is a good idea to subscribe to this event handler before calling (even if it is normally not needed to subscribe to any output device). + The contains a which allows you to react to all possible scenarios and to process all these events. + Note: This implementation ensures, that the event will be executed in the main thread the subscriber executes in! + So when subscribing to this event from UI thread, the specified event delegate will also be called in that UI thread. + + + + + Returns , if this class is being disposed. + + + + + Returns the device handle for this output device. + + + + + Returns the device id (number) which was used to create this instance. + + + + + User instance data to be used when sending system-exclusive messages. + + + + + Returns if the Midi output device is opened - else . + + To open the Midi output device call the method. + When you are done with the Midi input device you might call to actually close the device. + Use the methods to send any message to the . + + + + + Returns the last Midi error code (see for possible values). + + + + + Definition of the and event handler. + + Set to the resp. the object instance that raised the event. + An instance of the event args containing the event details. + + This definition complies with the .NET Framework's standard for event handlers. + + + + + Types of Midi message event that has occurred with the resp. class. + + + A variable of this type is passed inside the object + for the or event. + + + + + The Midi device was opened. + Message: Not used (null). + + + + + The Midi device was closed (any device handle is no longer valid from this point on). + Message: Not used (null). + + + + + The Midi device was started. + Message: The Midi device ID started (int). + + + + + The Midi device was stopped (Midi messages will no longer being send). + Message: The Midi device ID stopped (int). + + + + + A Midi short message was received by the device (only valid for a ). + Message: . + + + + + A Midi system-exclusive message was received by the device (valid for a and a ). + Message: . + + + + + An invalid Midi short message was received by the device (only valid for a ). + Message: (constructed even if invalid). + + + + + An invalid Midi system-exclusive message was received by the device (valid for a and a ). + Message: (constructed even if invalid). + + + + + A Midi system-exclusive message was processed by the output device (valid for a only). + Message: (as send via ). + + + + + EventArgs class to be passed as the second parameter of a or event handler. + + + This class provides all the information relevant to a Midi message event which might occur to a or class. + + + + + Initializes a new instance of the MidiMessageEventArgs class by initializing all of its properties. + + The type of event which occurred (see ). + The Midi device ID associated to this event. + The Midi device handle associated to this event. + The data which should be passed along with the message event (depending on the event type this could be a , or ). + + + + Gets the type of event which occurred. + + + + + Gets the Midi device ID on which the event occurred. + + + + + Gets the Midi device handle on which the event occurred. + + + + + Gets the message which was passed along with the event. + + + + + Gets the Midi short message which was passed along with the event. + + Should only be used, if the is or . + For other event types this property will return . + + + + + Returns , if a Midi short message was passed along with the event (else ). + + + + + Gets the Midi system-exclusive message which was passed along with the event. + + Should only be used, if the is , or . + For other event types this property will return . + + + + + Returns , if a Midi system-exclusive message which was passed along with the event (else ). + + + + + General list of Midi Error Codes. + + In order to retrieve a textual description of the error code use . + + + + no error + + + + + unspecified error + + + + + device ID out of range + + + + + driver failed enable + + + + + device already allocated + + + + + device handle is invalid + + + + + no device driver present + + + + + memory allocation error + + + + + function isn't supported + + + + + error value out of range + + + + + invalid flag passed + + + + + invalid parameter passed + + + + + handle being used + + + + + specified alias not found + + + + + bad registry database + + + + + registry key not found + + + + + registry read error + + + + + registry write error + + + + + registry delete error + + + + + registry value not found + + + + + driver does not call DriverCallback + + + + + header not prepared + + + + + still something playing + + + + + no configured instruments + + + + + hardware is still busy + + + + + port no longer connected + + + + + invalid MIF + + + + + operation unsupported w/ open mode + + + + + thru device 'eating' a message + + + + + General Midi Flags. + + + + + No callback. + + + + + To be used with or to define the general Midi callback procedure address. + + + + + When this parameter is also specified with the MIDI_CALLBACK_FUNCTION, then MIM_MOREDATA messages are sent to the callback function as well as MIM_DATA messages. + + + + + Midi Message Types. + + + + + The MIM_OPEN message is sent to a MIDI input callback function when a MIDI input device is opened. + + + Parameters: + param1Not used. + param2Not used. + + + + + + + The MIM_CLOSE message is sent to a MIDI input callback function when a MIDI input device is closed. + + + Parameters: + param1Not used. + param2Not used. + + + The device handle is no longer valid after this message has been sent. + + + + + The MIM_DATA message is sent to a MIDI input callback function when a MIDI message is received by a MIDI input device. + + + Parameters: + param1MIDI message that was received. The message is packed into a doubleword value as follows: + High word: High-order byte: Not used. Low-order byte: Contains a second byte of MIDI data (when needed). + Low word: High-order byte: Contains the first byte of MIDI data (when needed). Low-order byte: Contains the MIDI status. + The two MIDI data bytes are optional, depending on the MIDI status byte. + + param2Time that the message was received by the input device driver. The time stamp is specified in milliseconds, beginning at zero when the function was called. + + + MIDI messages received from a MIDI input port have running status disabled; each message is expanded to include the MIDI status byte. + This message is not sent when a MIDI system-exclusive message is received. + You might used the class to construct and or unpack the message into it's components. + + + + + The MIM_LONGDATA message is sent to a MIDI input callback function when a system-exclusive buffer has been filled with data and is being returned to the application. + + + Parameters: + param1Pointer to a structure identifying the input buffer. + param2Time that the message was received by the input device driver. The time stamp is specified in milliseconds, beginning at zero when the function was called. + + + The returned buffer might not be full. To determine the number of bytes recorded into the returned buffer, use the member of the MIDI_HEADER structure specified by param1. + + + + + The MIM_ERROR message is sent to a MIDI input callback function when an invalid MIDI message is received. + + + Parameters: + param1Invalid MIDI message that was received. The message is packed into a doubleword value with the first byte of the message in the low-order byte. + param2Time that the message was received by the input device driver. The time stamp is specified in milliseconds, beginning at zero when the function was called. + + + + + + + The MIM_LONGERROR message is sent to a MIDI input callback function when an invalid or incomplete MIDI system-exclusive message is received. + + + Parameters: + param1Pointer to a structure identifying the buffer containing the invalid message. + param2Time that the message was received by the input device driver. The time stamp is specified in milliseconds, beginning at zero when the function was called. + + + The returned buffer might not be full. To determine the number of bytes recorded into the returned buffer, use the member of the MIDI_HEADER structure specified by param1. + + + + + The MIM_MOREDATA message is sent to a MIDI input callback function when a MIDI message is received by a MIDI input device but the application is not processing MIM_DATA messages fast enough to keep up with the input device driver. The callback function receives this message only when the application specifies MIDI_IO_STATUS in the call to the function. + + + Parameters: + param1MIDI message that was received. The message is packed into a doubleword value as follows: + High word: High-order byte: Not used. Low-order byte: Contains a second byte of MIDI data (when needed). + Low word: High-order byte: Contains the first byte of MIDI data (when needed). Low-order byte: Contains the MIDI status. + The two MIDI data bytes are optional, depending on the MIDI status byte. + + param2Time that the message was received by the input device driver. The time stamp is specified in milliseconds, beginning at zero when the function was called. + + + An application should do only a minimal amount of processing of MIM_MOREDATA messages. (In particular, applications should not call the PostMessage function while processing MIM_MOREDATA.) Instead, the application should place the event data into a buffer and then return. + When an application receives an MIM_DATA message after a series of MIM_MOREDATA messages, it has caught up with incoming MIDI events and can safely call time-intensive functions. + MIDI messages received from a MIDI input port have running status disabled; each message is expanded to include the MIDI status byte. + This message is not sent when a MIDI system-exclusive message is received. + You might used the class to construct and or unpack the message into it's components. + + + + + The MOM_OPEN message is sent to a MIDI output callback function when a MIDI output device is opened. + + + Parameters: + param1Not used. + param2Not used. + + + + + + + The MOM_CLOSE message is sent to a MIDI output callback function when a MIDI output device is closed. + + + Parameters: + param1Not used. + param2Not used. + + + The device handle is no longer valid after this message has been sent. + + + + + The MOM_DONE message is sent to a MIDI output callback function when the specified system-exclusive or stream buffer has been played and is being returned to the application. + + + Parameters: + param1Pointer to a structure identifying the input buffer. + param2Not used. + + + + + + + Type of the MIDI output device, to be used with the flag field. + + + + + Unknown MIDI device. + + + + + MIDI hardware port. + + + + + Synthesizer. + + + + + Square wave synthesizer. + + + + + FM synthesizer. + + + + + Microsoft MIDI mapper. + + + + + Hardware wavetable synthesizer. + + + + + Software synthesizer. + + + + + Flag of the flags property. + + + + + Unprepared. No flags set. + + + + + Set by the device driver to indicate that it is finished with the buffer and is returning it to the application. + + + + + Set by Windows to indicate that the buffer has been prepared by using the or function. + + + + + Set by Windows to indicate that the buffer is queued for playback. + + + + + Set to indicate that the buffer is a stream buffer. + + + + + Defines constants representing MIDI message types. + + + + + Unknown Message type (see ). + All messages, which do not conform a , , or message are considered as unknown. + + + + + A Channel Message (see ). + The status byte is split into two halfs (the 4 high-bits contains the type and the 4 lower-bits contain the controler channel number). + The data byte 1 and data byte 2 might be used. Some messages occure in pairs meaning a second message will provide additional data bytes. + The following status is recognized as Channel messages: , , , , , and . + + + + + A SystemCommon Message (see ). + The status byte contains the message type itself. + The data byte 1 and data byte 2 might be used. Some messages are spaned over multiple messages to provide additional data bytes. + The following status is recognized as SystemCommon messages: , , and . + + + + + A SystemRealtime Message (see ). + The status byte contains the message type itself. + No data bytes are used with SystemRealtime messages. + The following status is recognized as SystemRealtime messages: , , , , , and . + + + + + A SystemExclusive Message (see ). + + + + + Defines constants for Midi message status. + + + + + No status. + + + + + Channel Message: Note Off. + Status: 0x80 to 0x8F where the low nibble is the MIDI channel. + Data1: The first data is the note number. There are 128 possible notes on a MIDI device, numbered 0 to 127 (where Middle C is note number 60). This indicates which note should be released. + Data2: The second data byte is the velocity, a value from 0 to 127. This indicates how quickly the note should be released (where 127 is the fastest). It's up to a MIDI device how it uses velocity information. Often velocity will be used to tailor the VCA release time. MIDI devices that can generate Note Off messages, but don't implement velocity features, will transmit Note Off messages with a preset velocity of 64. + This status might also be used, if the Midi message actually returned 'NoteOn' but with a velocity (data2) of 0. The class already translates those messages to NoteOff (see ). + An 'AllNotesOff' ControlChange message can be used to turn off all notes for which a device received NoteOn messages (without having received respective Note Off messages). + + + + + Channel Message: Note On. + Status: 0x90 to 0x9F where the low nibble is the MIDI channel. + Data1: The first data is the note number. There are 128 possible notes on a MIDI device, numbered 0 to 127 (where Middle C is note number 60). This indicates which note should be played. + Data2: The second data byte is the velocity, a value from 0 to 127. This indicates with how much force the note should be played (where 127 is the most force). It's up to a MIDI device how it uses velocity information. Often velocity is be used to tailor the VCA attack time and/or attack level (and therefore the overall volume of the note). MIDI devices that can generate Note On messages, but don't implement velocity features, will transmit Note On messages with a preset velocity of 64. + NoteOn message that has a velocity of 0 is considered to actually be a NoteOff message!, and the respective note is therefore released. The class already translates those messages to NoteOff (see ). + An 'AllNotesOff' ControlChange message can be used to turn off all notes for which a device received NoteOn messages (without having received respective Note Off messages). + + + + + Channel Message: Polyphonic Aftertouch (Polyphonic Pressure). + Status: 0xA0 to 0xAF where the low nibble is the MIDI channel. + Data1: The first data is the note number. There are 128 possible notes on a MIDI device, numbered 0 to 127 (where Middle C is note number 60). This indicates to which note the pressure is being applied. + Data2: The second data byte is the pressure amount, a value from 0 to 127 (where 127 is the most pressure). + + + + + Channel Message: Control Change. + Status: 0xB0 to 0xBF where the low nibble is the MIDI channel. + Data1: The first data is the controller number (0 to 127). This indicates which controller is affected by the received MIDI message. + Data2: The second data byte is the value to which the controller should be set, a value from 0 to 127. + Some Midi data messages might actually use two sub-sequent short messages to construct a paired message representing a single value range (e.g. the with a ). + This to support paired values with a higher resolution (16384 instead of 128 values). The same might apply the the controller value itself. + In such case two short messages will be send, where one contains the LSB value (single steps) in it's or byte and the other message contains the MSB value (128th steps) in it's or byte. + Typically the messages with a of and with a value between 0 and 31 (MSB) are paired with a message of a value between 32 and 63 (LSB). + But also a value of 98 (LSB) will be paired with a value of 99 (MSB) as well as a value of 100 (LSB) will be paired with a value of 101 (MSB). + Other pairs might be hardware specific. + An 'AllControllersOff' ControlChange message can be used to reset all controllers (that a MIDI device implements) to default values. + See the for a list of defined controller numbers for more information about particular controllers. + + + + + Channel Message: Program Change. + Status: 0xC0 to 0xCF where the low nibble is the MIDI channel. + Data1: The program number to change to, a number from 0 to 127. + Data2: not used. + + + + + Channel Message: Channel Pressure (Channel Aftertouch). + Status: 0xC0 to 0xCF where the low nibble is the MIDI channel. + Data1: The program number to change to, a number from 0 to 127. + Data2: not used. + If multiple banks do exist a ProgramChange command will select a new program number from the current bank only. + A different bank will be selected with two sub-sequent commands. This will also be called a BankSelect command. + + + + + Channel Message: Pitch Bend. + Status: 0xE0 to 0xEF where the low nibble is the MIDI channel. + Data1: The first data byte's bits 0 to 6 are bits 0 to 6 of the 14-bit value. + Data2: The second data byte's bits 0 to 6 are really bits 7 to 13 of the 14-bit value. + The two data bytes should be combined together to form a single 14-bit value. + A combined value of 0x2000 is meant to indicate that the Pitch Wheel is centered (ie, the sounding notes aren't being transposed up or down). Higher values transpose pitch up, and lower values transpose pitch down. + + + + + SystemExclusive Message: Start of system-exclusive message. + Status: 0xF0. + Various data bytes will follow, finally ending with an . + + + + + SystemCommon Message: MIDI Time Code (see for details). + Status: 0xF1. + Data1: It's the time code value, a number from 0 to 127. + Data2: not used. + The two data bytes should be combined together to form a single 14-bit value. + See the for details. + + + + + SystemCommon Message: Song Position Pointer. + Status: 0xF2. + Data1: The first data byte's bits 0 to 6 are bits 0 to 6 of the 14-bit value. + Data2: The second data byte's bits 0 to 6 are really bits 7 to 13 of the 14-bit value. + The two data bytes should be combined together to form a single 14-bit value. + This 14-bit value is the MIDI Beat upon which to start the song. Songs are always assumed to start on a MIDI Beat of 0. Each MIDI Beat spans 6 MIDI Clocks. In other words, each MIDI Beat is a 16th note (since there are 24 MIDI Clocks in a quarter note). + + + + + SystemCommon Message: Song Select. + Status: 0xF3. + Data1: The song number, a value from 0 to 127. + Data2: not used. + + + + + SystemCommon Message: Tune Request. + Status: 0xF6. + Data1: not used. + Data2: not used. + + + + + SystemExclusive Message: End of system-exclusive message. + Status: 0xF7. + No data bytes should follow. + + + + + SystemRealtime Message: Timing Clock. + Status: 0xF8. + Data1: not used. + Data2: not used. + There are 24 MIDI Clocks in every quarter note. (12 MIDI Clocks in an eighth note, 6 MIDI Clocks in a 16th, etc). Therefore, when a slave device counts down the receipt of 24 MIDI Clock messages, it knows that one quarter note has passed. + + + + + SystemRealtime Message: Tick System Realtime. + Status: 0xF9. + Data1: not used. + Data2: not used. + While a master device's 'Clock' is playing back, it will send a continuous stream of MIDI Tick events at a rate of one per every 10 milliseconds. + + + + + SystemRealtime Message: Start. + Status: 0xFA. + Data1: not used. + Data2: not used. + MIDI Start always begins playback at MIDI Beat 0 (ie, the very beginning of the song). So, when a slave device receives a MIDI Start, it automatically resets its "Song Position" to 0. If the device needs to start playback at some other point (either set by a previous Song Position Pointer message, or manually by the musician), then MIDI Continue is used instead of MIDI Start. + + + + + SystemRealtime Message: Continue. + Status: 0xFB. + Data1: not used. + Data2: not used. + Often, the slave device has its playback tempo synced to the master via MIDI Clock. + + + + + SystemRealtime Message: Stop. + Status: 0xFC. + Data1: not used. + Data2: not used. + When a device receives a MIDI Stop, it should keep track of the point at which it stopped playback (ie, its stopped "Song Position"), in the anticipation that a MIDI Continue might be received next. + + + + + SystemRealtime Message: Active Sense. + Status: 0xFE. + Data1: not used. + Data2: not used. + A device sends out an Active Sense message (at least once) every 300 milliseconds if there has been no other activity on the MIDI buss, to let other devices know that there is still a good MIDI connection between the devices. + This is an optional feature that only a few devices implement. Many devices don't ever initiate this minimal "safety" feature. + + + + + SystemRealtime Message: System Reset. + Status: 0xFF. + Data1: not used. + Data2: not used. + A Reset message should never be sent automatically by any MIDI device. Rather, this should only be sent when a musician specifically tells a device to do so. + + + + + Defines constants for controller types. + + + + + Controller-Pair: The Bank Select coarse (0=MSB, 32=LSB). + + + + + Controller-Pair: The Modulation Wheel coarse (1=MSB, 33=LSB). + + + + + Controller-Pair: The Breath Control coarse (2=MSB, 34=LSB). + + + + + Controller-Pair: Un- or User defined controller 3 (3=MSB, 35=LSB). + + + + + Controller-Pair: The Foot Pedal coarse (4=MSB, 36=LSB). + + + + + Controller-Pair: The Portamento Time coarse (5=MSB, 37=LSB). + + + + + Controller-Pair: The Data Entry Slider coarse (6=MSB, 38=LSB). + + + + + Controller-Pair: The Volume coarse (7=MSB, 39=LSB). + + + + + Controller-Pair: The Balance coarse (8=MSB, 40=LSB). + + + + + Controller-Pair: Un- or User defined controller 9 (9=MSB, 41=LSB). + + + + + Controller-Pair: The Pan position coarse (10=MSB, 42=LSB). + + + + + Controller-Pair: The Expression coarse (11=MSB, 43=LSB). + + + + + Controller-Pair: The Effect Control 1 coarse (12=MSB, 44=LSB). + + + + + Controller-Pair: The Effect Control 2 coarse (13=MSB, 45=LSB). + + + + + Controller-Pair: Un- or User defined controller 14 (14=MSB, 46=LSB). + + + + + Controller-Pair: Un- or User defined controller 15 (15=MSB, 47=LSB). + + + + + Controller-Pair: The General Puprose Slider 1 (16=MSB, 48=LSB). + + + + + Controller-Pair: The General Puprose Slider 2 (17=MSB, 49=LSB). + + + + + Controller-Pair: The General Puprose Slider 3 (18=MSB, 50=LSB). + + + + + Controller-Pair: The General Puprose Slider 4 (19=MSB, 51=LSB). + + + + + Controller-Pair: Un- or User defined controller 20 (20=MSB, 52=LSB). + + + + + Controller-Pair: Un- or User defined controller 21 (21=MSB, 53=LSB). + + + + + Controller-Pair: Un- or User defined controller 22 (22=MSB, 54=LSB). + + + + + Controller-Pair: Un- or User defined controller 23 (23=MSB, 55=LSB). + + + + + Controller-Pair: Un- or User defined controller 24 (24=MSB, 56=LSB). + + + + + Controller-Pair: Un- or User defined controller 25 (25=MSB, 57=LSB). + + + + + Controller-Pair: Un- or User defined controller 26 (26=MSB, 58=LSB). + + + + + Controller-Pair: Un- or User defined controller 27 (27=MSB, 59=LSB). + + + + + Controller-Pair: Un- or User defined controller 28 (28=MSB, 60=LSB). + + + + + Controller-Pair: Un- or User defined controller 29 (29=MSB, 61=LSB). + + + + + Controller-Pair: Un- or User defined controller 30 (30=MSB, 62=LSB). + + + + + Controller-Pair: Un- or User defined controller 31 (31=MSB, 63=LSB). + + + + + Controller-Pair: The Bank Select coarse (0=MSB, 32=LSB). + + + + + Controller-Pair: The Modulation Wheel coarse (1=MSB, 33=LSB). + + + + + Controller-Pair: The Breath Control coarse (2=MSB, 34=LSB). + + + + + Controller-Pair: Un- or User defined controller 3 (3=MSB, 35=LSB). + + + + + Controller-Pair: The Foot Pedal coarse (4=MSB, 36=LSB). + + + + + Controller-Pair: The Portamento Time coarse (5=MSB, 37=LSB). + + + + + Controller-Pair: The Data Entry Slider coarse (6=MSB, 38=LSB). + + + + + Controller-Pair: The Volume coarse (7=MSB, 39=LSB). + + + + + Controller-Pair: The Balance coarse (8=MSB, 40=LSB). + + + + + Controller-Pair: Un- or User defined controller 9 (9=MSB, 41=LSB). + + + + + Controller-Pair: The Pan position coarse (10=MSB, 42=LSB). + + + + + Controller-Pair: The Expression coarse (11=MSB, 43=LSB). + + + + + Controller-Pair: The Effect Control 1 coarse (12=MSB, 44=LSB). + + + + + Controller-Pair: The Effect Control 2 coarse (13=MSB, 45=LSB). + + + + + Controller-Pair: Un- or User defined controller 14 (14=MSB, 46=LSB). + + + + + Controller-Pair: Un- or User defined controller 15 (15=MSB, 47=LSB). + + + + + Controller-Pair: The General Puprose Slider 1 (16=MSB, 48=LSB). + + + + + Controller-Pair: The General Puprose Slider 2 (17=MSB, 49=LSB). + + + + + Controller-Pair: The General Puprose Slider 3 (18=MSB, 50=LSB). + + + + + Controller-Pair: The General Puprose Slider 4 (19=MSB, 51=LSB). + + + + + Controller-Pair: Un- or User defined controller 20 (20=MSB, 52=LSB). + + + + + Controller-Pair: Un- or User defined controller 21 (21=MSB, 53=LSB). + + + + + Controller-Pair: Un- or User defined controller 22 (22=MSB, 54=LSB). + + + + + Controller-Pair: Un- or User defined controller 23 (23=MSB, 55=LSB). + + + + + Controller-Pair: Un- or User defined controller 24 (24=MSB, 56=LSB). + + + + + Controller-Pair: Un- or User defined controller 25 (25=MSB, 57=LSB). + + + + + Controller-Pair: Un- or User defined controller 26 (26=MSB, 58=LSB). + + + + + Controller-Pair: Un- or User defined controller 27 (27=MSB, 59=LSB). + + + + + Controller-Pair: Un- or User defined controller 28 (28=MSB, 60=LSB). + + + + + Controller-Pair: Un- or User defined controller 29 (29=MSB, 61=LSB). + + + + + Controller-Pair: Un- or User defined controller 30 (30=MSB, 62=LSB). + + + + + Controller-Pair: Un- or User defined controller 31 (31=MSB, 63=LSB). + + + + + Non-Continuous: The Hold Pedal 1. + + + + + Non-Continuous: The Portamento. + + + + + Non-Continuous: The Sustenuto Pedal. + + + + + Non-Continuous: The Soft Pedal. + + + + + Non-Continuous: The Legato Pedal. + + + + + Non-Continuous: The Hold Pedal 2. + + + + + The Sound Variation. + + + + + The Sound Timbre. + + + + + The Sound Release Time. + + + + + The Sound Attack Time. + + + + + The Sound Brightness. + + + + + The Sound Control 6. + + + + + The Sound Control 7. + + + + + The Sound Control 8. + + + + + The Sound Control 9. + + + + + The Sound Control 10. + + + + + The General Purpose Button 1. + + + + + The General Purpose Button 2. + + + + + The General Purpose Button 3. + + + + + The General Purpose Button 4. + + + + + The General Purpose Button 5. + + + + + The General Purpose Button 6. + + + + + The General Purpose Button 7. + + + + + The General Purpose Button 8. + + + + + The General Purpose Button 9. + + + + + The General Purpose Button 10. + + + + + The General Purpose Button 11. + + + + + The Effects Level. + + + + + The Tremelo Level. + + + + + The Chorus Level. + + + + + The Celeste Level. + + + + + The Phaser Level. + + + + + The Data Button Increment. + + + + + The Data Button Decrement. + + + + + Controller-Pair: The NonRegistered Parameter Fine. + + + + + Controller-Pair: The NonRegistered Parameter Coarse. + + + + + Controller-Pair: The Registered Parameter Fine. + + + + + Controller-Pair: The Registered Parameter Coarse. + + + + + User Controller 102. + + + + + User Controller 103. + + + + + User Controller 104. + + + + + User Controller 105. + + + + + User Controller 106. + + + + + User Controller 107. + + + + + User Controller 108. + + + + + User Controller 109. + + + + + User Controller 110. + + + + + User Controller 111. + + + + + User Controller 112. + + + + + User Controller 113. + + + + + User Controller 114. + + + + + User Controller 115. + + + + + User Controller 116. + + + + + User Controller 117. + + + + + User Controller 118. + + + + + User Controller 119. + + + + + ChannelMode: The All Sound Off. + + + + + ChannelMode: Reset all controllers to default. + + + + + ChannelMode: The Local Keyboard. + + + + + ChannelMode: The All Notes Off. + + + + + ChannelMode: The Omni Mode Off. + + + + + ChannelMode: The Omni Mode On. + + + + + ChannelMode:The Mono Operation (mono mode on and poly mode off). + + + + + ChannelMode: The Poly Operation (mono mode off and poly mode on). + + + + + Defines constants representing the 12 Note of the chromatic scale. + + + + + C natural. + + + + + C sharp. + + + + + D natural. + + + + + D sharp. + + + + + E natural. + + + + + F natural. + + + + + F sharp. + + + + + G natural. + + + + + G sharp. + + + + + A natural. + + + + + A sharp. + + + + + B natural. + + + + + Lowest note on a 88th keyboard (A-1). + + + + + Lowest note on a 76th keyboard (E0). + + + + + Lowest note on a 61th keyboard (C1). + + + + + Middle C (C3). + + + + + Standard Pitch (A3). + + + + + Highest note on a 61th keyboard (C6). + + + + + Highest note on a 76th keyboard (G6). + + + + + Highest note on a 88th keyboard (C7). + + + + + Highest Midi note (G8). + + + + + Defines constants representing the Midi Time Code (MTC) type used by the status given in a member (also see and ). + + + MIDI Time Code (MTC) is a sub-protocol within MIDI, and is used to keep 2 devices that control some sort of timed performance (ie, maybe a sequencer and a video deck) in sync. MTC messages are an alternative to using MIDI Clocks and Song Position Pointer messages. MTC is essentially SMPTE mutated for transmission over MIDI. SMPTE timing is referenced from an absolute "time of day". On the other hand, MIDI Clocks and Song Position Pointer are based upon musical beats from the start of a song, played at a specific Tempo. For many (non-musical) cues, it's easier for humans to reference time in some absolute way rather than based upon musical beats at a certain tempo. + The Midi Time Code is used by the if the is . It is also often called the Quarter Frame message. + It has a status of 0xF1, and one subsequent data byte. This message is sent periodically to keep track of the running SMPTE time. It's analogous to the MIDI Clock message. The Quarter Frame messages are sent at a rate of 4 per each SMPTE Frame. In other words, by the time that a slave has received 4 Quarter Frame messages, a SMPTE Frame has passed. So, the Quarter Frame messages provide a "sub-frame" clock reference. (With 30 fps SMPTE, this "clock tick" happens every 8.3 milliseconds). + But the Quarter Frame is more than just a quarter frame "clock tick". The Quarter Frame message's data byte contains the SMPTE time (ie, hours, minutes, seconds, and frames). SMPTE time is normally expressed in 80 bits. Obviously, this is too many bits to be contained in 1 8-bit data byte. So, each Quarter Frame message contains just one piece of the time (for example, one Quarter Frame may contain only the hours). In order to get the entire SMPTE time at any given point, a slave needs to receive several Quarter Frame messages, and piece the current SMPTE time together from those messages. It takes 8 Quarter Frame messages to convey the current SMPTE time. In other words, by the time that a slave can piece together the current SMPTE time, two SMPTE frames have passed (ie, since there are 4 Quarter Frame messages in each frame). So, MTC's version of SMPTE time actually counts in increments of 2 SMPTE Frames per each update of the current SMPTE time. + The first (of 8) Quarter Frame message contains the low nibble (ie, bits 0 to 3) of the Frame Time. The second Quarter Frame message contains the high nibble (ie, bits 4 to 7) of the Frame Time. The third and fourth messages contain the low and high nibbles of the Seconds Time. The fifth and sixth messages contain the low and high nibbles of the Minutes Time. The seventh and eighth messages contain the low and high nibbles of the Hours Time. The eighth message also contains the SMPTE frames-per-second Type (ie, 24, 25, 30 drop, or 30 fps). If you were to break up the Quarter Frame's data byte into its 7 bits, the format is: + "0nnn dddd" (8-bits). + Where 'nnn' is one of 7 possible values which tell you what 'dddd' represents. This enummeration represents the 7 values, and what each causes 'dddd' to represent. + + When MTC is running in the forward direction (ie, time is advancing), the Quarter Frame messages are sent in the order of Frames Low Nibble to Hours High Nibble. In other words, the order looks something like this: + 0xF1 0x0n : where n is the current Frames Low Nibble. + 0xF1 0x1n : where n is the current Frames High Nibble. + 0xF1 0x2n : where n is the current Seconds Low Nibble. + 0xF1 0x3n : where n is the current Seconds High Nibble. + 0xF1 0x4n : where n is the current Minutes Low Nibble. + 0xF1 0x5n : where n is the current Minutes High Nibble. + 0xF1 0x6n : where n is the current Hours Low Nibble. + 0xF1 0x7n : where n is the current Hours High Nibble and SMPTE Type. + When MTC is running in reverse (ie, time is going backwards), these are sent in the opposite order, ie, the Hours High Nibble is sent first and the Frames Low Nibble is last. + The arrival of the 0xF1 0x0n and 0xF1 0x4n messages always denote where SMPTE Frames actually occur in realtime. + Since 8 Quarter Frame messages are required to piece together the current SMPTE time, timing lock can't be achieved until the slave has received all 8 messages. This will take from 2 to 4 SMPTE Frames, depending upon when the slave comes online. + The Frame number (contained in the first 2 Quarter Frame messages) is the SMPTE Frames Time for when the first Quarter Frame message is sent. But, because it takes 7 more Quarter Frames to piece together the current SMPTE Time, when the slave does finally piece the time together, it is actually 2 SMPTE Frames behind the real current time. So, for display purposes, the slave should always add 2 frames to the current time. + + + + + Current Frames Low Nibble. + + + + + Current Frames High Nibble. + + + + + Current Seconds Low Nibble. + + + + + Current Seconds High Nibble. + + + + + Current Minutes Low Nibble. + + + + + Current Minutes High Nibble. + + + + + Current Hours Low Nibble. + + + + + Current Hours High Nibble and SMPTE Type. + In the data byte for the Hours High Nibble and SMPTE Type, the bits are interpreted as follows: + "0nnn x yy d" (8-bits). + Where 'nnn' is 7. 'x' is unused and set to 0. 'd' is bit 4 of the Hours Time. 'yy' tells the SMPTE Type as follows: + 0 = 24 fps, 1 = 25 fps, 2 = 30 fps (Drop-Frame), 3 = 30 fps + + + + + Defines constants representing the Midi timing format used by the structure. + + + + + Time in milliseconds. + + + + + Number of waveform-audio samples. + + + + + Current byte offset from beginning of the file. + + + + + SMPTE (Society of Motion Picture and Television Engineers) time. + + + + + MIDI time. + + + + + Ticks within a MIDI stream. + + + + + Defines constants representing the special Midi ManufacturerID within a system-exclusive message (see for details). + + This list does NOT define the real manufacturer id's but only special purpose manufacturer IDs! + + + + To accomodate a greater range of manufacturer IDs, the MMA decided to reserve a manufacturer ID of 0 for a special purpose. + When you see a manufacturer ID of 0, then there will be two more data bytes after this. These two data bytes combine to make the real manufacturer ID. + So, some manufacturers have IDs that are 3 bytes, where the first byte is always 0. + Using this "trick", the range of unique manufacturer IDs is extended to accomodate over 16,000 MIDI manufacturers. + + + + + A manufacturer must get a registered ID from the MMA if he wants to define his own SysEx messages, or use this one. + This ID is for educational or development use only, and should never appear in a commercial design. + + + + + Universal SysEx messages: realtime messages (ie, ones that need to be responded to immediately). + After the ID byte is a SysEx Channel byte. This could be from 0 to 127 for a total of 128 SysEx channels. + So, although "normal" SysEx messages have no MIDI channel like Voice Category messages do, a Universal SysEx message can be sent on one of 128 SysEx channels. + This allows the musician to set various devices to ignore certain Universal SysEx messages (ie, if the device allows the musician to set its Base SysEx Channel. + Most devices just set their Base SysEx channel to the same number as the Base Channel for Voice Category messages). + On the other hand, a SysEx channel of 127 is actually meant to tell the device to "disregard the channel and pay attention to this message regardless". + After the SysEx channel, the next two bytes are Sub IDs which tell what the SysEx is for. + There are several Sub IDs defined for particular messages. There is a Sub ID for a Universal SysEx message to set a device's master volume. (This is different than Volume controller which sets the volume for only one particular MIDI channel). + There is a Sub ID for a Universal SysEx message to set a device's Pitch Wheel bend range. There are a couple of Sub IDs for some Universal SysEx messages to implement a waveform (sample) dump over MIDI etc. + + + + + Universal SysEx messages: non-realtime (ie, ones which can be processed when the device gets around to it). + After the ID byte is a SysEx Channel byte. This could be from 0 to 127 for a total of 128 SysEx channels. + So, although "normal" SysEx messages have no MIDI channel like Voice Category messages do, a Universal SysEx message can be sent on one of 128 SysEx channels. + This allows the musician to set various devices to ignore certain Universal SysEx messages (ie, if the device allows the musician to set its Base SysEx Channel. + Most devices just set their Base SysEx channel to the same number as the Base Channel for Voice Category messages). + On the other hand, a SysEx channel of 127 is actually meant to tell the device to "disregard the channel and pay attention to this message regardless". + After the SysEx channel, the next two bytes are Sub IDs which tell what the SysEx is for. + There are several Sub IDs defined for particular messages. There is a Sub ID for a Universal SysEx message to set a device's master volume. (This is different than Volume controller which sets the volume for only one particular MIDI channel). + There is a Sub ID for a Universal SysEx message to set a device's Pitch Wheel bend range. There are a couple of Sub IDs for some Universal SysEx messages to implement a waveform (sample) dump over MIDI etc. + + + + + Represents MIDI input device capabilities as returned by the method. + + + + + Manufacturer identifier of the device driver for the MIDI input device. + + + + + Product identifier of the MIDI input device. + + + + + Version number of the device driver for the MIDI input device. + + The high-order byte is the major version number, and the low-order byte is the minor version number. + + + + Product name in a null-terminated string. + + + + + Reserved; must be zero. + + + + + Default Constructor. + + + + + Returns the name of the Midi input device. + + The name of the input device. + + + + Represents MIDI output device capabilities as returned by the method. + + + + + Manufacturer identifier of the device driver for the MIDI output device. + + + + + Product identifier of the MIDI output device. + + + + + Version number of the device driver for the MIDI output device. + + The high-order byte is the major version number, and the low-order byte is the minor version number. + + + + Product name in a null-terminated string. + + + + + Type of the MIDI output device. + + This value can be one of the values. + + + + Number of voices supported by an internal synthesizer device. + + If the device is a port, this member is not meaningful and is set to 0. + + + + Maximum number of simultaneous notes that can be played by an internal synthesizer device. + + If the device is a port, this member is not meaningful and is set to 0. + + + + Channels that an internal synthesizer device responds to. + + + The least significant bit refers to channel 0 and the most significant bit to channel 15. + Port devices that transmit on all channels set this member to 0xFFFF. + + + + + Optional functionality supported by the device. + + It can be one or more of the following: + MIDICAPS_CACHE (0x0004) : Supports patch caching. + MIDICAPS_LRVOLUME (0x0002) : Supports separate left and right volume control. + MIDICAPS_STREAM (0x0008) : Provides direct support for the StreamOut function. + MIDICAPS_VOLUME (0x0001) : Supports volume control. + If a device supports volume changes, the MIDICAPS_VOLUME flag will be set for the support member. If a device supports separate volume changes on the left and right channels, both the MIDICAPS_VOLUME and the MIDICAPS_LRVOLUME flags will be set for this member. + + + + + Default Constructor. + + + + + Returns the name of the Midi output device. + + The name of the output device. + + + + Supports patch caching? + + + + + Supports separate left and right volume control? + + + + + Supports volume control? + + + + + Provides direct support for the StreamOut function? + + + + + Is the device a Midi output port? + + + + + Is the device a Midi mapper? + + + + + Represents the Windows Multimedia MIDIHDR structure. + + + + + Pointer to MIDI data. + + Typically a pointer to a byte array containing the data or a null-terminated string of 8-bit Windows (ANSI) characters. + + + + Size of the buffer. + + + + + Actual amount of data in the buffer. + + This value should be less than or equal to the value given in the member. + + + + Custom user data. + + + + + Flags giving information about the buffer (see for more information). + + + + + Reserved for driver (do not use). + + + + + Reserved for driver (do not use). + + + + + Offset into the buffer when a callback is performed. + + This callback is generated because the MEVT_F_CALLBACK flag is set in the event member of the MidiEventArgs structure. + This offset enables an application to determine which event caused the callback. + + + + + Reserved for MMSYSTEM (do not use). + + + + + Initializes a new instance of the MIDI_HEADER. + + + In order to use the MIDIHDR with a Midi function (e.g. or ) you must first call the / methods. + Make sure, that you always call / once you prepared the header in order to release all unmanaged recourses! + + + + + Returns the recorded data buffer as a string. + + The string representation of the Midi data in the header buffer. + If no pointer to the data exists will be returned. If the bytesRecorded is zero an empty string will be returned - + else a hexadecimal representation of the byte array of the data will be returned, e.g. "F0 41 00 ... F7". + + + + Returns the Midi data member as a byte array. + + The available data as a byte[] (will return if no data is present or an empty array, if the bytesRecorded member is zero). + + + + Resets all internal values. + + + + + Indicate if the device driver is finished with the buffer and is returning it to the application. + + + + + Indicate if the buffer has been prepared by using the or function. + + + + + Indicate if the buffer is a stream buffer. + + + + + Represents a wrapper for the Windows Multimedia MIDIHDR structure. + + + In order to use the MIDI_HEADER with a Midi function (e.g. or ) you must first call the method which provides a to be used. + After you send a system-exclusive data block, you must wait until the device driver is finished with the data block before freeing it. If you are sending multiple data blocks, you must monitor the completion of each data block so you know when to send additional blocks. + Once the MIDI_HEADER is used, your application will be notified with a callback procedure (see or ) when a system-exclusive buffer has been filled with data and is being returned to the application. + The message is sent to a MIDI input callback function - the message is sent to a MIDI output callback function in such case. + The param1 parameter of the callback will give you the pointer to the MIDI_HEADER structure identifying the input buffer. + Use the constructor taking a headerPtr to create a MIDI_HEADER from such pointer! + Make sure, that you always call once you prepared the header with the method in order to release all unmanaged recourses (this is at best done within the callback procedure)! + Internally the and methods will use the , resp. , . + + + + + Initializes a new instance of the MIDI_HEADER with an empty data buffer of the given size. + + The number of bytes for the data buffer (between 2 and 65536). + + If a is given outside the range of 2 and 65536 the default size of 256 will be used. + In order to use the MIDI_HEADER with a Midi function (e.g. or ) you must first call the method which provides a to be used. + Make sure, that you always call once you prepared the header with the method and received back the header from the Midi device in order to release all unmanaged recourses! + + + + + Initializes a new instance of the MIDI_HEADER with the given data buffer. + + The byte array to use as the data buffer. + + In order to use the MIDI_HEADER with a Midi function (e.g. or ) you must first call the method which provides a to be used. + Make sure, that you always call once you prepared the header with the method and received back the header from the Midi device in order to release all unmanaged recourses! + + + + + Initializes a new instance of the MIDI_HEADER with the string as the data buffer. + + The string to use as the data buffer (the string characters will be copied to the buffer as byte values plus a final terminating null-byte). + + In order to use the MIDI_HEADER with a Midi function (e.g. or ) you must first call the method which provides a to be used. + Make sure, that you always call once you prepared the header with the method and received back the header from the Midi device in order to release all unmanaged recourses! + + + + + Initializes a new instance of the MIDI_HEADER from a given Midi header pointer. + + The pointer to the MIDIHDR structure (e.g. as received in a or ). + + In order to use the MIDI_HEADER with a Midi function (e.g. or ) you must first call the method which provides a to be used. + After you send a system-exclusive data block, you must wait until the device driver is finished with the data block before freeing it. If you are sending multiple data blocks, you must monitor the completion of each data block so you know when to send additional blocks. + Once the MIDI_HEADER is used, your application will be notified with a callback procedure (see or ) when a system-exclusive buffer has been filled with data and is being returned to the application. + The message is sent to a MIDI input callback function - the message is sent to a MIDI output callback function in such case. + The param1 parameter of the callback will give you the pointer to the MIDI_HEADER structure identifying the input buffer. + Use this method to create a MIDI_HEADER from such pointer! + Make sure, that you always call in order to release all unmanaged recourses (this is at best done within the callback procedure)! + + + + + Returns the buffer as a string. + + The string representation of the Midi data in the header buffer. + If no data exists an empty string will be returned - else a hexadecimal representation of the byte array of the data will be returned, e.g. "F0 41 00 ... F7". + + + + Prepares the MIDI_HEADER structure and sets the member. + + Dealing with a Midi input device? (=input, =output). + The handle to the MIDI device. + on success (use the to access the prepared MIDIHDR structure) - else . + + The returned can be used e.g. with the or methods. + Internally the MIDIHDR (see ) will be prepared using the resp. depending on the parameter. + Note: This method allocates unmanaged memory and copies this MIDI_HEADER structure to that memory. + So there is no need to keep a reference to the MIDI_HEADER instance in your application, since you will be notified in a or when the Midi device has finished with the buffer and provides back a pointer to the MIDIHDR structure. + You might then use the constructor overload taking a headerPtr to (re)create an instance of this class. + Make sure, that you always call in order to release all unmanaged recourses (this is at best done within the callback procedure)! + + + + + Unprepares the MIDI_HEADER structure and frees all used resources. + + Dealing with a Midi input device? (=input, =output). + The handle to the MIDI device. + This function is complementary to . You must call this method in order to free all uses and allocated resources. + After passing a MIDIHDR structure to a Midi device by using the or function, you must wait until the driver is finished with the MIDIHDR before using (this is at best done within the callback procedure resp. ). + + + + + The MIDI data buffer. + + Typically a byte array containing the data or a null-terminated string of 8-bit Windows (ANSI) characters. + Once you prepared the data buffer with you might not change the buffer. + + + + + Custom user data. + + + Once you prepared the data buffer with you might not change the user data. + + + + + Gets the flags giving information about the buffer (see for more information). + + + + + Gets the pointer to the prepared MIDIHDR structure (or if the header was not prepared). + + Access this member to retrieve a pointer to the MIDIHDR structure. + In order to use the MIDI_HEADER with a Midi function (e.g. or ) you must first call the method which provides this member. + Make sure, that you always call once you prepared the header with the method and received back the header from the Midi device in order to release all unmanaged recourses! + + + + + Indicates if the device driver is finished with the buffer and is returning it to the application. + + + + + Indicates if the buffer has been prepared by using the method. + + + + + Indicates if the buffer is a stream buffer. + + + + + Represents the Windows Multimedia MMTIME structure. + + The MIDI_TIME structure contains timing information for different types of multimedia data. + + + + Time format. It can be one of the following values (see ). + + + + + Number of milliseconds. Used when type is . + + + + + Number of samples. Used when type is . + + + + + Byte count. Used when type is . + + + + + Ticks in MIDI stream. Used when type is . + + + + + Hours - SMPTE time structure. Used when type is . + + + + + Minutes - SMPTE time structure. Used when type is . + + + + + Seconds - SMPTE time structure. Used when type is . + + + + + Frames - SMPTE time structure. Used when type is . + + + + + Frames per second (24, 25, 29 (30 drop), or 30) - SMPTE time structure. Used when type is . + + + + + Dummy byte for alignment - SMPTE time structure. Used when type is . + + + + + Padding1 - SMPTE time structure. Used when type is . + + + + + Padding2 - SMPTE time structure. Used when type is . + + + + + Song pointer position. MIDI time structure. Used when type is . + + + + + Represents the general callback delegate for handling Midi Output messages. + + Handle to the MIDI output device. + MIDI output message (one of the ). + Instance data supplied with the method. + Message parameter 1. + Message parameter 2. + + NOTE: , and are implemented here as IntPtr values for maximum Win32 and Win64 compatibility. + If the parameters are actually numerial values you might use the ToInt32() resp. ToInt64() members to convert to these values. + The meaning of the and parameters is specific to the message type. + The message might be used with the class to construct and unpack the message into it's components. + If param1 contains a pointer to a structure you might use the constructor overload taking a headerPtr in order to create an instance of a MIDI_HEADER in such case. + Applications should not call any system-defined functions from inside a callback function, except for , . Calling other wave functions will cause deadlock. + Also note, that you should not make any GUI control changes within this procedure. If needed use an Invoke to make sure to execute GUI changes in the related GUI thread. + + + + private MIDIOUTPROC _midiProc; + private IntPtr _midiOutHandle; + ... + // Open the Midi device #2 + _midiProc = new MIDIOUTPROC(MyMidiProc); + MIDIError ret = Midi.MIDI_OutOpen(ref _midiOutHandle, 2, _midiProc, 0); + if (ret == MIDIError.MIDI_OK) + { + // output ready + } + ... + // when not needed anymore...stop the device + Midi.MIDI_OutReset(_midiOutHandle); + // and close the device + Midi.MIDI_OutClose(_midiOutHandle); + ... + + private void Send(int handle, int message) + { + int result = MIDI_OutShortMsg(handle, message); + } + + private void SendSysExBuffer(IntPtr handle, byte[] data) + { + MIDI_HEADER header = new MIDI_HEADER(data); + header.Prepare(false, handle); + // If the header was perpared successfully. + if (header.HeaderPtr != IntPtr.Zero) + { + // send a system-exclusive message to the output device + Midi.MIDI_OutLongMsg(handle, header.HeaderPtr); + } + } + + public void MyMidiProc(IntPtr handle, MIDIMessage msg, IntPtr instance, IntPtr param1, IntPtr param2) + { + // handle all Midi messages here + if(msg == MIDIMessage.MOM_OPEN) + { + // nothing to do + } + else if (msg == MIDIMessage.MOM_CLOSE) + { + // handle is from now on invalid + } + else if (msg == MIDIMessage.MOM_DONE) + { + // process the message... + // param1 will contain the pointer to the MIDI_HEADER + MIDI_HEADER header = new MIDI_HEADER(param1); + byte[] data = header.Data; + header.Unprepare(false, handle); + ... + // or + MidiSysExMessage sysExMsg = new MidiSysExMessage(false, handle, param1); + ... + } + } + + + Private _midiProc As MIDIOUTPROC + Private _midiOutHandle As IntPtr + ... + ' Open the Midi device #2 + _midiProc = New MIDIOUTPROC(AddressOf MyMidiProc) + Dim ret As MIDIError = Midi.MIDI_OutOpen(_midiOutHandle, 2, _midiProc, 0) + If ret = MIDIError.MIDI_OK Then + ' output ready + End If + ... + ' when not needed anymore...stop the device + Midi.MIDI_OutReset(_midiOutHandle) + ' and close the device + Midi.MIDI_OutClose(_midiOutHandle) + ... + + Private Sub Send(handle As Integer, message As Integer) + Dim result As Integer = MIDI_OutShortMsg(handle, message) + End Sub + + Private Sub SendSysExBuffer(handle As IntPtr, data() As Byte) + Dim header As New MIDI_HEADER(data) + header.Prepare(False, handle) + ' If the header was perpared successfully. + If header.HeaderPtr <> IntPtr.Zero Then + ' send a system-exclusive message to the output device + Midi.MIDI_OutLongMsg(handle, header.HeaderPtr) + End If + End Sub + + Public Sub MyMidiProc(handle As IntPtr, msg As MIDIMessage, instance As IntPtr, param1 As IntPtr, param2 As IntPtr) + ' handle all Midi messages here + If msg = MIDIMessage.MOM_OPEN Then + ' nothing to do + Else + If msg = MIDIMessage.MOM_CLOSE Then + ' handle is from now on invalid + Else + If msg = MIDIMessage.MOM_DONE Then + ' process the message... + ' param1 will contain the pointer to the MIDI_HEADER + Dim header As New MIDI_HEADER(param1) + Dim data As Byte() = header.Data + header.Unprepare(False, handle) + ... + ' or + Dim sysExMsg As New MidiSysExMessage(False, handle, param1) + ... + End If + End If + End If + End Sub + + + + + + Represents the general callback delegate for handling Midi Input messages. + + Handle to the MIDI input device. + MIDI input message (one of the MIM_xxx values, see ). + Instance data supplied with the method. + Message parameter 1. + Message parameter 2. + + NOTE: , and are implemented here as IntPtr values for maximum Win32 and Win64 compatibility. + If the parameters are actually numerial values you might use the ToInt32() resp. ToInt64() members to convert to these values. + The meaning of the and parameters is specific to the message type. For more info see . + The or message might be used with the class to construct and unpack the message into it's components. + The or message might be used with the class to construct and unpack the message into it's components. + If param1 contains a pointer to a structure you might use the constructor overload taking a headerPtr in order to create an instance of a MIDI_HEADER in such case. + Applications should not call any system-defined functions from inside a callback function, except for , . + Also note, that you should not make any GUI control changes within this procedure. If needed use an Invoke to make sure to execute GUI changes in the related GUI thread. + + + + private MIDIINPROC _midiProc; + private IntPtr _midiInHandle; + ... + // Open the Midi device #2 + _midiProc = new MIDIINPROC(MyMidiProc); + MIDIError ret = Midi.MIDI_InOpen(ref _midiInHandle, 2, _midiProc, IntPtr.Zero, MIDIFlags.MIDI_IO_STATUS); + if (ret == MIDIError.MIDI_OK) + { + // supply the device with 2 buffers + AddSysExBuffer(_midiInHandle, 1024); + AddSysExBuffer(_midiInHandle, 1024); + // Start the device + ret = Midi.MIDI_InStart(_midiInHandle); + } + ... + // Stop the device + Midi.MIDI_InReset(_midiInHandle); + // when not needed anymore...close the device + Midi.MIDI_InClose(_midiInHandle); + ... + // prepare receiving system-exclusive messages + private void AddSysExBuffer(IntPtr handle, int size) + { + // prepare a empty midi header + MIDI_HEADER header = new MIDI_HEADER(size); + header.Prepare(true, handle); + // If the header was perpared successfully. + if (header.HeaderPtr != IntPtr.Zero) + { + // Add the buffer to the InputDevice. + Midi.MIDI_InAddBuffer(handle, header.HeaderPtr); + } + } + + public void MyMidiProc(IntPtr handle, MIDIMessage msg, IntPtr instance, IntPtr param1, IntPtr param2) + { + // handle all Midi messages here + if (msg == MIDIMessage.MIM_OPEN) + { + // nothing to do + } + else if (msg == MIDIMessage.MIM_CLOSE) + { + // handle is from now on invalid + } + else if (msg == MIDIMessage.MIM_DATA) + { + // process the message... + int p1 = param1.ToInt32(); + int p2 = param2.ToInt32(); + ... + // or + MidiShortMessage shortMsg = new MidiShortMessage(param1, param2); + ... + } + else if (msg == MIDIMessage.MIM_MOREDATA) + { + // we are not fast enough in this callback to keep up + // the input device is sending messages to fast + ... + } + else if (msg == MIDIMessage.MIM_LONGDATA) + { + // process the message... + // param1 will contain the pointer to the MIDI_HEADER + MIDI_HEADER header = MIDI_HEADER(param1); + byte[] data = header.Data; + ... + header.Unprepare(true, handle); + // add a new buffer + // since we should constantly provide new buffers until we finished recording + AddSysExBuffer(handle, 1024); + } + else if (msg == MIDIMessage.MIM_ERROR) + { + // process the invalid message... + MidiShortMessage errorMsg = new MidiShortMessage(param1, param2); + ... + } + else if (msg == MIDIMessage.MIM_LONGERROR) + { + // process the invalid message... + // param1 will contain the pointer to the MIDI_HEADER + MidiSysExMessage errorSysExMsg = new MidiSysExMessage(true, handle, param1); + ... + // add a new buffer + // since we should constantly provide new buffers until we finished recording + AddSysExBuffer(handle, 1024); + } + } + + + Private _midiProc As MIDIINPROC + Private _midiInHandle As IntPtr + ... + ' Open the Midi device #2 + _midiProc = New MIDIINPROC(AddressOf MyMidiProc) + Dim ret As MIDIError = Midi.MIDI_InOpen(_midiInHandle, 2, _midiProc, IntPtr.Zero, MIDIFlags.MIDI_IO_STATUS) + If ret = MIDIError.MIDI_OK Then + ' supply the device with 2 buffers + AddSysExBuffer(_midiInHandle, 1024) + AddSysExBuffer(_midiInHandle, 1024) + ' Start the device + ret = Midi.MIDI_InStart(_midiInHandle) + End If + ... + ' Stop the device + Midi.MIDI_InReset(_midiInHandle) + ' when not needed anymore...close the device + Midi.MIDI_InClose(_midiInHandle) + ... + ' prepare receiving system-exclusive messages + Private Sub AddSysExBuffer(handle As IntPtr, size As Integer) + ' prepare a empty midi header + Dim header As New MIDI_HEADER(size) + header.Prepare(True, handle) + ' If the header was perpared successfully. + If header.HeaderPtr <> IntPtr.Zero Then + ' Add the buffer to the InputDevice. + Midi.MIDI_InAddBuffer(handle, header.HeaderPtr) + End If + End Sub + + Public Sub MyMidiProc(handle As IntPtr, msg As MIDIMessage, instance As IntPtr, param1 As IntPtr, param2 As IntPtr) + ' handle all Midi messages here + If msg = MIDIMessage.MIM_OPEN Then + ' nothing to do + Else + If msg = MIDIMessage.MIM_CLOSE Then + ' handle is from now on invalid + Else + If msg = MIDIMessage.MIM_DATA Then + ' process the message... + Dim p1 As Integer = param1.ToInt32() + Dim p2 As Integer = param2.ToInt32() + ... + ' or + Dim shortMsg As New MidiShortMessage(param1, param2) + ... + Else + If msg = MIDIMessage.MIM_MOREDATA Then + ' we are not fast enough in this callback to keep up + ' the input device is sending messages to fast + ... + Else + If msg = MIDIMessage.MIM_LONGDATA Then + ' process the message... + ' param1 will contain the pointer to the MIDI_HEADER + Dim header As MIDI_HEADER = MIDI_HEADER(param1) + Dim data As Byte() = header.Data + ... + header.Unprepare(True, handle) + ' add a new buffer + ' since we should constantly provide new buffers until we finished recording + AddSysExBuffer(handle, 1024) + Else + If msg = MIDIMessage.MIM_ERROR Then + ' process the invalid message... + Dim errorMsg As New MidiShortMessage(param1, param2) + ... + Else + If msg = MIDIMessage.MIM_LONGERROR Then + ' process the invalid message... + ' param1 will contain the pointer to the MIDI_HEADER + Dim errorSysExMsg As New MidiSysExMessage(True, handle, param1) + ... + ' add a new buffer + ' since we should constantly provide new buffers until we finished recording + AddSysExBuffer(handle, 1024) + End If + End If + End If + End If + End If + End If + End If + End Sub + + + + + + Provides general methods to save an audio stream to a file in the WAVE file format. + Supported bit resolutions are 8-bit, 16-bit, 24-bit and 32-bit. + Supported sample rates are 8000, 11025, 22050, 44100, 48000 or 96000 Hz. + Multi channel wave files are also supported. Use 1=mono, 2=stereo... + + + The WaveWriter class is an internal implementation of the BASS.NET API and does not require any additional extension or add-on to the BASS audio library. + The typical use of this class is as followed: + a) Create an instance of the class and define the frequency, channels and bitrate. + b) Call the method subsequently to write sample data to the wave file. + c) Finally call to close and finish the wave file. + Note: Not all media players support playback of all formats, especially multi-channel (more than stereo) or high-resolution (greater 16-bit) wave files. + The following speaker assignment is used for multi-channel wave files (as defined/recommended by Microsoft): + + #ChansSpeaker Assignment + 1Mono: SPEAKER_FRONT_LEFT + 2Stereo: SPEAKER_FRONT_LEFT, SPEAKER_FRONT_RIGHT + 32.1: SPEAKER_FRONT_LEFT, SPEAKER_FRONT_RIGHT, SPEAKER_FRONT_CENTER + 42.2: SPEAKER_FRONT_LEFT, SPEAKER_FRONT_RIGHT, SPEAKER_BACK_LEFT, SPEAKER_BACK_RIGHT + 52.2.1: SPEAKER_FRONT_LEFT, SPEAKER_FRONT_RIGHT, SPEAKER_FRONT_CENTER, SPEAKER_BACK_LEFT, SPEAKER_BACK_RIGHT + 65.1: SPEAKER_FRONT_LEFT, SPEAKER_FRONT_RIGHT, SPEAKER_FRONT_CENTER, SPEAKER_LOW_FREQUENCY, SPEAKER_BACK_LEFT, SPEAKER_BACK_RIGHT + 75.1.1: SPEAKER_FRONT_LEFT, SPEAKER_FRONT_RIGHT, SPEAKER_FRONT_CENTER, SPEAKER_LOW_FREQUENCY, SPEAKER_BACK_LEFT, SPEAKER_BACK_RIGHT, SPEAKER_BACK_CENTER + 87.1: SPEAKER_FRONT_LEFT, SPEAKER_FRONT_RIGHT, SPEAKER_FRONT_CENTER, SPEAKER_LOW_FREQUENCY, SPEAKER_BACK_LEFT, SPEAKER_BACK_RIGHT, SPEAKER_FRONT_LEFT_OF_CENTER, SPEAKER_FRONT_RIGHT_OF_CENTER + 97.1.1: SPEAKER_FRONT_LEFT, SPEAKER_FRONT_RIGHT, SPEAKER_FRONT_CENTER, SPEAKER_LOW_FREQUENCY, SPEAKER_BACK_LEFT, SPEAKER_BACK_RIGHT, SPEAKER_FRONT_LEFT_OF_CENTER, SPEAKER_FRONT_RIGHT_OF_CENTER, SPEAKER_BACK_CENTER + > 9Undefined: SPEAKER_ALL + + + + + Writing a MP3 file to WAV: + + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_STREAM_DECODE); + WaveWriter WW = new WaveWriter("test.wav", stream, true); + short[] data = new short[32768]; + while (Bass.BASS_ChannelIsActive(stream) == BASSActive.BASS_ACTIVE_PLAYING) + { + int length = Bass.BASS_ChannelGetData(stream, data, 32768); + if (length > 0) + WW.Write(data, length); + } + // finilize the wave file! + WW.Close(); + Bass.BASS_StreamFree(stream); + + + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_STREAM_DECODE) + Dim WW As New WaveWriter("test.wav", stream, True) + Dim data(32768 - 1) As Short + While Bass.BASS_ChannelIsActive(stream) = BASSActive.BASS_ACTIVE_PLAYING + Dim length As Integer = Bass.BASS_ChannelGetData(stream, data, 32768) + If length > 0 Then + WW.Write(data, length) + End If + End While + ' finilize the wave file! + WW.Close() + Bass.BASS_StreamFree(stream) + + Using a WaveWriter in a RECORDPROC to record 24-bit at 44.1kHz, stereo: + + private WaveWriter _waveWriter = null; // make it global, so that the GC can not remove it + private RECORDPROC _myRecProc; + private int _recHandle = 0; + ... + // start recording + _myRecProc = new RECORDPROC(MyRecording); + _recHandle = Bass.BASS_RecordStart(44100, 2, + BASSFlag.BASS_RECORD_PAUSE | BASSFlag.BASS_SAMPLE_FLOAT, _myRecProc, IntPtr.Zero); + // create a WaveWriter using the _recHandle to set the freq. and channels, but write the wave at 24-bit + _waveWriter = new WaveWriter( "test.wav", _recHandle, 24, true); + Bass.BASS_ChannelPlay(_recHandle, false); + ... + // when finished recording call this! + if (_waveWriter != null) + { + // finilize the wave file! + _waveWriter.Close(); + } + ... + // the recording callback + private bool MyRecording(int handle, IntPtr buffer, int length, IntPtr user) + { + // we will get float sample data here + // so make sure the _waveWriter.OrigResolution property is set to 32 + // this was automatically done, since we started recording with BASSFlag.BASS_SAMPLE_FLOAT + _waveWriter.Write( buffer, length ); + return true; // always continue recording + } + + + Private _waveWriter As WaveWriter = Nothing ' make it global, so that the GC can not remove it + Private _myRecProc As RECORDPROC + Private _recHandle As Integer = 0 + ... + ' start recording + _myRecProc = New RECORDPROC(AddressOf MyRecording) + _recHandle = Bass.BASS_RecordStart(44100, 2, + BASSFlag.BASS_RECORD_PAUSE Or BASSFlag.BASS_SAMPLE_FLOAT, _myRecProc, IntPtr.Zero) + ' create a WaveWriter using the _recHandle to set the freq. and channels, but write the wave at 24-bit + _waveWriter = New WaveWriter("test.wav", _recHandle, 24, True) + Bass.BASS_ChannelPlay(_recHandle, False) + ... + ' when finished recording call this! + If Not (_waveWriter Is Nothing) Then + ' finilize the wave file! + _waveWriter.Close() + End If + ... + ' the recording callback + Private Function MyRecording(handle As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Boolean + ' we will get float sample data here + ' so make sure the _waveWriter.OrigResolution property is set to 32 + ' this was automatically done, since we started recording with BASSFlag.BASS_SAMPLE_FLOAT + _waveWriter.Write(buffer, length) + Return True ' always continue recording + End Function + + + + + + Create a WaveWrite instance from a given BASS stream channel. + + Fully referenced path and file name of the Wave file to create. + A BASS stream channel (HMUSIC, HSTREAM, HRECORD) for which to create a WaveWriter. + Specifies, if an existing should be overwritten (=overwrite, =do not overwrite). + The sample data provided when calling the method must conform the stream info settings. No resampling will be applied here. + This overload already sets the , and properties according to the given stream. + When you have created the stream with the flag the Wave file will be written in 32-bit float format (WAVE_FORMAT_IEEE_FLOAT). + When you have created the stream with the flag the Wave file will be written in 8-bit unsigned format (WAVE_FORMAT_PCM). + In all other cases the the Wave file will be written in 16-bit signed format (WAVE_FORMAT_PCM). + Note: 24-bit resolutions are not supported with this overload. + If the stream contains more than 2 channels (e.g. multi-channel) the Wave file will be written in the WAVE_FORMAT_EXTENSIBLE format. + + The channel information could not be retrieved for the . + The file already exists (only raised if the has not been used). Or the Wave Header could not be written. + + + + Create a WaveWrite instance from a given BASS stream channel. + + Fully referenced path and file name of the Wave file to create. + A BASS stream channel (HMUSIC, HSTREAM, HRECORD) for which to create a WaveWriter. + Bits per sample of the wave file (must be either 8, 16, 24 or 32). This overrides the actual stream resolution and the bit rate will be converted automatically (however quality might be effected but never increased). + Specifies, if an existing should be overwritten (=overwrite, =do not overwrite). + The sample data provided when calling the method must conform the stream info settings. No resampling will be applied here. + This overload already sets the and properties according to the given stream. The will be overwritten. + When you have specified a 32-bit resolution the Wave file will be written in 32-bit float format (WAVE_FORMAT_IEEE_FLOAT). + When you have specified an 8-bit resolution the Wave file will be written in 8-bit unsigned format (WAVE_FORMAT_PCM). + In all other cases the the Wave file will be written in 16-bit or 24-bit signed format (WAVE_FORMAT_PCM). + If the stream contains more than 2 channels (e.g. multi-channel) the Wave file will be written in the WAVE_FORMAT_EXTENSIBLE format. + + The channel information could not be retrieved for the . + The file already exists (only raised if the has not been used). Or the Wave Header could not be written. + + + + Create a WaveWrite instance to save sample data to be processed to a wave file. + + Fully referenced path and file name of the Wave file to create. + Number of channels of the wave file (1=mono, 2=stereo...). + Sample rate of the wave file (e.g. 8000, 11025, 22050, 44100, 48000, 96000) in Hz. + Bits per sample of the wave file (must be either 8, 16, 24 or 32). + Specifies, if an existing should be overwritten (=overwrite, =do not overwrite). + The sample data provided when calling the method must conform these settings (ie. , and )! No resampling will be applied here. + When you have specified 24 the sample data must be provided as float values when using the method (the float sample will actually be converted to 24-bit samples)! + If the stream contains more than 2 channels (e.g. multi-channel) or is defined with 24-bit resolution the Wave file will be written in the WAVE_FORMAT_EXTENSIBLE format. + + The file already exists (only raised if the has not been used). Or the Wave Header could not be written. + + + + Internal constructor only. + + Overwrite flag. + + + + Disposes the current instance of the WaveWriter and all it's resources. + + + + + Finalization code. + + This destructor will run only if the method does not get called. + It will automatically the and flush all the data so far written. + + + + Writes the Wave Header structure to the BinaryWriter _bw. + + + + + Use this method to provide the sample data to the WaveWriter and write these samples to the wave file. + + The IntPtr containing the sample data. + The number of BYTEs in the buffer. + This method is best used in , or callback delegates. + Please note, that the sample data provided in the must conform the property! + Meaning if the =32 float sample data is expected, if =16 short sample data is expected and if =8 byte samples are expected! + However, the data written to the wave file will be in resolution (as specified in the constructor). If the is different from this one an automatic bit resolution conversion will take place. + When using a decoding stream other overloads might be more conviniant. + + + Using a WaveWriter in a RECORDPROC to record 24-bit at 44.1kHz, stereo: + + private WaveWriter _waveWriter = null; // make it global, so that the GC can not remove it + private RECORDPROC _myRecProc; + private int _recHandle = 0; + ... + // start recording + _myRecProc = new RECORDPROC(MyRecording); + _recHandle = Bass.BASS_RecordStart(44100, 2, + BASSFlag.BASS_RECORD_PAUSE | BASSFlag.BASS_SAMPLE_FLOAT, _myRecProc, IntPtr.Zero); + // create a WaveWriter using the _recHandle to set the freq. and channels, but write the wave at 24-bit + _waveWriter = new WaveWriter( "test.wav", _recHandle, 24, true); + Bass.BASS_ChannelPlay(_recHandle, false); + ... + // when finished recording call this! + if (_waveWriter != null) + { + // finilize the wave file! + _waveWriter.Close(); + } + ... + // the recording callback + private bool MyRecording(int handle, IntPtr buffer, int length, IntPtr user) + { + // we will get float sample data here + // so make sure the _waveWriter.OrigResolution property is set to 32 + // this was automatically done, since we started recording with BASSFlag.BASS_SAMPLE_FLOAT + _waveWriter.Write( buffer, length ); + return true; // always continue recording + } + + + Private _waveWriter As WaveWriter = Nothing ' make it global, so that the GC can not remove it + Private _myRecProc As RECORDPROC + Private _recHandle As Integer = 0 + ... + ' start recording + _myRecProc = New RECORDPROC(AddressOf MyRecording) + _recHandle = Bass.BASS_RecordStart(44100, 2, + BASSFlag.BASS_RECORD_PAUSE Or BASSFlag.BASS_SAMPLE_FLOAT, _myRecProc, IntPtr.Zero) + ' create a WaveWriter using the _recHandle to set the freq. and channels, but write the wave at 24-bit + _waveWriter = New WaveWriter("test.wav", _recHandle, 24, True) + Bass.BASS_ChannelPlay(_recHandle, False) + ... + ' when finished recording call this! + If Not (_waveWriter Is Nothing) Then + ' finilize the wave file! + _waveWriter.Close() + End If + ... + ' the recording callback + Private Function MyRecording(handle As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Boolean + ' we will get float sample data here + ' so make sure the _waveWriter.OrigResolution property is set to 32 + ' this was automatically done, since we started recording with BASSFlag.BASS_SAMPLE_FLOAT + _waveWriter.Write(buffer, length) + Return True ' always continue recording + End Function + + + + + + Use this method to provide 32-bit sample data to the WaveWriter and write these samples to the wave file. + + An array of float values to write to the wave file. + The number of BYTEs in the buffer. + This method is best used with e.g. and e.g. decoding channels. + The data written to the wave file will be in resolution (as specified in the constructor). + If this is not 32 (float) an automatic bit resolution conversion will take place. + + + Converting an OGG file to WAV (32-bit quality): + + // create a stream with the float option + int stream = Bass.BASS_StreamCreateFile("test.ogg", 0, 0, + BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); + // set the target bit resolution to 32 + WaveWriter WW = new WaveWriter("test.wav", stream, 32, true); + float[] data = new float[32768]; + while (Bass.BASS_ChannelIsActive(stream) == BASSActive.BASS_ACTIVE_PLAYING) + { + // get the sample data as float values as well + int length = Bass.BASS_ChannelGetData(stream, data, 32768); + // and write the data to the wave file + if (length > 0) + WW.Write(data, length); + } + // finilize the wave file! + WW.Close(); + Bass.BASS_StreamFree(stream); + + + ' create a stream with the float option + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.ogg", 0, 0, + BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT) + ' set the target bit resolution to 32 + Dim WW As New WaveWriter("test.wav", stream, 32, True) + Dim data(32768 - 1) As Single + While Bass.BASS_ChannelIsActive(stream) = BASSActive.BASS_ACTIVE_PLAYING + ' get the sample data as float values as well + Dim length As Integer = Bass.BASS_ChannelGetData(stream, data, 32768) + ' and write the data to the wave file + If length > 0 Then + WW.Write(data, length) + End If + End While + ' finilize the wave file! + WW.Close() + Bass.BASS_StreamFree(stream) + + + + + + Use this method to provide 16-bit sample data to the WaveWriter and write these samples to the wave file. + + An array of short values to write to the wave file. + The number of BYTEs in the buffer. + This method is best used with e.g. and e.g. decoding channels. + However, the data written to the wave file will be in resolution (as specified in the constructor). + If this is not 16 (short) an automatic bit resolution conversion will take place. + + + Writing a MP3 file to WAV: + + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_STREAM_DECODE); + WaveWriter WW = new WaveWriter("test.wav", stream, true); + short[] data = new short[32768]; + while (Bass.BASS_ChannelIsActive(stream) == BASSActive.BASS_ACTIVE_PLAYING) + { + int length = Bass.BASS_ChannelGetData(stream, data, 32768); + if (length > 0) + WW.Write(data, length); + } + // finilize the wave file! + WW.Close(); + Bass.BASS_StreamFree(stream); + + + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_STREAM_DECODE) + Dim WW As New WaveWriter("test.wav", stream, True) + Dim data(32768 - 1) As Short + While Bass.BASS_ChannelIsActive(stream) = BASSActive.BASS_ACTIVE_PLAYING + Dim length As Integer = Bass.BASS_ChannelGetData(stream, data, 32768) + If length > 0 Then + WW.Write(data, length) + End If + End While + ' finilize the wave file! + WW.Close() + Bass.BASS_StreamFree(stream) + + + + + + Use this method to provide 8-bit sample data to the WaveWriter and write these samples to the wave file. + + An array of byte values to write to the wave file. + The number of BYTEs in the buffer. + This method is best used with e.g. and e.g. decoding channels. + However, the data written to the wave file will be in resolution (as specified in the constructor). + If this is not 8 (byte) an automatic bit resolution conversion will take place. + + + Writing an OGG file to WAV (8-bit quality): + + int stream = Bass.BASS_StreamCreateFile("test.ogg", 0, 0, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_8BITS); + WaveWriter WW = new WaveWriter("test.wav", stream, true); + byte[] data = new byte[32768]; + while (Bass.BASS_ChannelIsActive(stream) == BASSActive.BASS_ACTIVE_PLAYING) + { + int length = Bass.BASS_ChannelGetData(stream, data, 32768); + if (length > 0) + WW.Write(data, length); + } + // finilize the wave file! + WW.Close(); + Bass.BASS_StreamFree(stream); + + + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.ogg", 0, 0, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_8BITS) + Dim WW As New WaveWriter("test.wav", stream, True) + Dim data(32768 - 1) As Byte + While Bass.BASS_ChannelIsActive(stream) = BASSActive.BASS_ACTIVE_PLAYING + Dim length As Integer = Bass.BASS_ChannelGetData(stream, data, 32768) + If length > 0 Then + WW.Write(data, length) + End If + End While + ' finilize the wave file! + WW.Close() + Bass.BASS_StreamFree(stream) + + + + + + Use this method to provide sample data to the WaveWriter and write these samples to the wave file. + + An array of byte values to write to the wave file. + The number of BYTEs in the buffer. + This method is best used with e.g. and e.g. decoding channels. + However, the data written to the wave file will NOT be converted and must be in the resolution (as specified in the constructor). + + + Writing an OGG file to WAV (8-bit quality): + + int stream = Bass.BASS_StreamCreateFile("test.ogg", 0, 0, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_8BITS); + WaveWriter WW = new WaveWriter("test.wav", stream, true); + byte[] data = new byte[32768]; + while (Bass.BASS_ChannelIsActive(stream) == BASSActive.BASS_ACTIVE_PLAYING) + { + int length = Bass.BASS_ChannelGetData(stream, data, 32768); + if (length > 0) + WW.WriteNoConvert(data, length); + } + // finilize the wave file! + WW.Close(); + Bass.BASS_StreamFree(stream); + + + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.ogg", 0, 0, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_8BITS) + Dim WW As New WaveWriter("test.wav", stream, True) + Dim data(32768 - 1) As Byte + While Bass.BASS_ChannelIsActive(stream) = BASSActive.BASS_ACTIVE_PLAYING + Dim length As Integer = Bass.BASS_ChannelGetData(stream, data, 32768) + If length > 0 Then + WW.WriteNoConvert(data, length) + End If + End While + ' finilize the wave file! + WW.Close() + Bass.BASS_StreamFree(stream) + + + + + + Closes the WaveWriter and underlying wave file and updates the wave header accordingly. + + After calling this method you might use the created wave file. + Not closing the WaveWriter will result in a broken wave file, since only at this point the wave header will be updated with the corrent sample size written. + + + + + Gets or Sets the fully referenced path and file name of the wave file to write to data to. + + + + + Gets the number of channels of the Wave file being created (values between 1 and 9 should be fine). + E.g. 1=mono, 2=stereo... + + + + + Gets the sample rate of the Wave file being created. + e.g. 44100 for 44.1kHz. Typically one of the following: 11025, 22050, 44100, 48000, 96000. + + + + + Gets or Sets the target resolution (number of bits per sample) of the Wave file being created. + This will be either 8, 16, 24 or 32. + + + + + Gets or Sets the original resolution (number of bits per sample) of the stream channel resp. sample data to process. + This should be either 8, 16 or 32. + This value is used in the methods to automatically convert the bit resolution according to the target value. + E.g. set this value to 32, if you receive 32-bit float sample data in a DSP callback and if you want to call the method there directly, but have specified a target resolution of 8, 16 or 24 bit. + + + + + Defines the possible wave formats (only a few and common are listed here). For a complete listing see the mmreg.h header file. + + + + + Unknown Format + + + + + PCM format (8 or 16 bit) + + + + + Float format (32 bit) + + + + + Extensible Format (user defined) + + + + + Wave speaker assignments for the WAVE_FORMAT_EXTENSIBLE format and multi-channel files. + + + + + Provides general methods to generate a stereo or mono channel waveform graphic for an audio file or a decoding stream handle. + The WaveForm will be drawn as two independent stereo envelopes, a combined dual mono envelope or a mono envelope. + Requires: bass.dll - available @ www.un4seen.com + + + The WaveForm class is an internal implementation of the BASS.NET API and does not require any additional extension or add-on to the BASS audio library, meaning only bass.dll is required. + However, must have been called before using any method within this class! + NOTE: When using the WaveForm class with an already existing decoding channel (created with the BASS_STREAM_DECODE flag) the data will be retrieved from that channel, meaning the data will be 'stolen'. + In such a case you must reset the position to the beginning of the stream afterwards, e.g. use before rendering the WaveForm and call when rendering of the WaveForm has been completed. + The typical use of this class is as followed: + a) create an instance of this class (e.g. together with the filename) + b) call to scan all peak levels + c) call to generate a wave form image + You might also use and to save or load a rendered wave form. + The methods and lets you manage named position markers within the WaveForm to be displayed, use the property to specify how and if markers should be displayed. + When the image of the rendered wave form or a zoomed window of it is created via the global properties , and as well as are used. + You might also access the scanned peak levels directly via the property. + + + + + Default constructor creating a new instance of the WaveForm class. + + + + + Creates a new instance of the WaveForm class, initializing the file name. + + The file name to render. + + + + Creates a new instance of the WaveForm class, initializing the file name and a notification handler. + + The file name to render. + A callback delegate to be invoked during the rendering progress. + An optional window control which will be used to invoke the (if set), so that the callback will be executed in the 'correct' GUI thread. + + + + Creates a clone. + + + + + + + Returns a new WaveForm instance which is a clone of the current one. + + Set this to if you also want the and array to be cloned - else they will be referenced. + The new (cloned) WaveForm - or on error. + + Note: The WaveForm must have been rendered before it might be cloned (i.e. must return and must return ). + + + + + Resets the wave form. + + + + + Start the rendering process for the specified decoding stream (peak levels will be scanned). + + A prepared decoding channel to use for rendering. + , if rendering should be performed in an independent threadpool thread (using a Normal priority). , if rendering should be executed synchronious. + , if rendering was started successfully, else . + This overload uses the specified decoding channel. It's position will be set to 0 first. The channel can not and should not be used by your application in the meantime until rendering has been finished! + The decoding channel will be freed automatically by this method after rendering has been finished! + + + + + Start the rendering process for the specified decoding stream (peak levels will be scanned). + + A prepared decoding channel to use for rendering. + , if rendering should be performed in an independent threadpool thread (using a Normal priority). , if rendering should be executed synchronious. + , if the should be freed after rendering. + , if rendering was started successfully, else . + This overload uses the specified decoding channel. It's position will be set to 0 first. The channel can not and should not be used by your application in the meantime until rendering has been finished! + The decoding channel will be freed automatically by this method after rendering has been finished! + + + + + Start the rendering process for the specified decoding stream (peak levels will be scanned). + + A prepared decoding channel to use for rendering. + , if rendering should be performed in an independent background thread. , if rendering should be executed synchronious. + The thread priority to be used with the background thread (note, that when using a Normal priority a ThreadPool thread will be used). + , if the should be freed after rendering. + , if rendering was started successfully, else . + This overload uses the specified decoding channel. It's position will be set to 0 first. The channel can not and should not be used by your application in the meantime until rendering has been finished! + + + + + Start the rendering process for the given (peak levels will be scanned). + + , if rendering should be performed in an independent threadpool thread (using a Normal priority). , if rendering should be executed synchronious. + A combination of the flags on how to create the decoding stream. The and flags will be added automatically here, if not already set! + , if rendering was started successfully, else . + This overload creates an internal decoding channel allowing to render the peak levels independently. + If you intend to use this overload to render the wave form in parallel while already playing out the file, it is recommended to specify the same flags as for your playing stream. + This is because , , , etc. would return different values if you specified different resolutions for your playing stream and your rendering stream (eg. a stream with BASS_SAMPLE_FLOAT would return twice as much bytes as a stream created with the default 16-bit resolution). + If your playing stream and this call uses different flags, you might use the method, so that the members , or + will return converted values according to your playing stream. + + + + + Start the rendering process for the given (peak levels will be scanned). + + , if rendering should be performed in an independent background thread. , if rendering should be executed synchronious. + The thread priority to be used with the background thread (note, that when using a Normal priority a ThreadPool thread will be used). + A combination of the flags on how to create the decoding stream. The and flags will be added automatically here, if not already set! + , if rendering was started successfully, else . + This overload creates an internal decoding channel allowing to render the peak levels independently. + If you intend to use this overload to render the wave form in parallel while already playing out the file, it is recommended to specify the same flags as for your playing stream. + This is because , , , etc. would return different values if you specified different resolutions for your playing stream and your rendering stream (eg. a stream with BASS_SAMPLE_FLOAT would return twice as much bytes as a stream created with the default 16-bit resolution). + If your playing stream and this call uses different flags, you might use the method, so that the members , or + will return converted values according to your playing stream. + + + + + Start the rendering process for audio data located at the position (peak levels will be scanned). + Note: The will be ignored. + + , if rendering should be performed in an independent background thread (using a Normal priority). , if rendering should be executed synchronious. + A combination of the flags on how to create the decoding stream. The and flags will be added automatically here, if not already set! + Set to to render from the file location given by - + else rendering will be performed + The length of the block (if specified). + , if rendering was started successfully, else . + This overload creates an internal decoding channel from the memory location given by allowing to render the peak levels independently. + If you intend to use this overload to render the wave form in parallel while already playing out the audio, it is recommended to specify the same flags as for your playing stream. + This is because , , , etc. would return different values if you specified different resolutions for your playing stream and your rendering stream (eg. a stream with BASS_SAMPLE_FLOAT would return twice as much bytes as a stream created with the default 16-bit resolution). + If your playing stream and this call uses different flags, you might use the method, so that the members , or + will return converted values according to your playing stream. + + + + + Start the rendering process for the given (peak levels will be scanned). + + , if rendering should be performed in an independent background thread. , if rendering should be executed synchronious. + The thread priority to be used with the background thread (note, that when using a Normal priority a ThreadPool thread will be used). + A combination of the flags on how to create the decoding stream. The and flags will be added automatically here, if not already set! + Set to to render from the file location given by - + else rendering will be performed by the audio data located at the position. + The length of the block (if specified). + , if rendering was started successfully, else . + This overload creates an internal decoding channel allowing to render the peak levels independently. + If you intend to use this overload to render the wave form in parallel while already playing out the file, it is recommended to specify the same flags as for your playing stream. + This is because , , , etc. would return different values if you specified different resolutions for your playing stream and your rendering stream (eg. a stream with BASS_SAMPLE_FLOAT would return twice as much bytes as a stream created with the default 16-bit resolution). + If your playing stream and this call uses different flags, you might use the method, so that the members , or + will return converted values according to your playing stream. + + + + + Stops a currently running rendering process. + + + + + Start a live recording rendering process for the specified non-decoding handle (peak levels will not be scanned at this point). + + The HRECORD or HSTREAM stream for which to render the WaveForm (e.g. as returned by ). + The initial rendering buffer length in seconds (e.g. 10sec. - minimum is 1sec.). + The next block in seconds when the recording buffer length needs to be increased (e.g. 5sec. - minimum is 1sec. or specify 0 to define a cycle buffer). + , if live recording rendering was started successfully, else . + The handle might be any stream channel. Just make sure, that you DO NOT use the method overload (which takes no parameters) with a decoding stream. + When rendering a WaveForm for live recording the total length of the recording is unknown. + Therefore a dynamic buffer is used internally which is initialized with a length of seconds. + When the buffer needs to be extended (e.g. the recording exceeds the initial length) it is incremented seconds. + When you finally stop the live rendering recording with the total buffer size is at least seconds big or a multiple of seconds. + Make sure you started recording via before calling any live rendering recording method. + After live rendering recorded has been started you might call to actual render the recorded sample data. + When you specify 0 (zero) for the parameter a cycle buffer is created. Meaning the rendered WaveForm buffer size will only be long. + When the buffer is filled, it starts at the beginning again (position 0)- overwriting the oldest rendered data. + + + + + Start a live recording rendering process for the specified stream handle (peak levels will not be scanned at this point). + + The HRECORD or HSTREAM stream for which to render the WaveForm (e.g. as returned by ). + The initial rendering buffer length in seconds (e.g. 10sec. - minimum is 1sec.). + The next block in seconds when the recording buffer length needs to be increased (e.g. 5sec. - minimum is 1sec. or specify 0 to define a cycle buffer). + , if live recording rendering was started successfully, else . + The handle might be any stream channel. Just make sure, that you DO NOT use the method overload (which takes no parameters) with a decoding stream. + When rendering a WaveForm for live recording the total length of the recording is unknown. + Therefore a dynamic buffer is used internally which is initialized with a length of seconds. + When the buffer needs to be extended (e.g. the recording exceeds the initial length) it is incremented seconds. + When you finally stop the live rendering recording with the total buffer size is at least seconds big or a multiple of seconds. + Make sure you started recording via before calling any live rendering recording method. + After live rendering recorded has been started you might call to actual render the recorded sample data. + When you specify 0 (zero) for the parameter a cycle buffer is created. Meaning the rendered WaveForm buffer size will only be long. + When the buffer is filled, it starts at the beginning again (position 0)- overwriting the oldest rendered data. + + + + + Stops live recording rendering. + + This just stops the live recording rendering of the WaveForm, but it does not stop the actual recording itself. + + + + Renders live recorded data and generates the WaveForm data for it. + + Call this method subsequently and often enough to get the actual recording data and perform the rendering of that data. + You must have started live rendering recording with before calling this method. + You might use the method either within a or via your own timer callback at any time when new sample data is available. + This overload actually calls internally, so it is not recommended to use this with a stream channel (but only with buffered recording channels), since it will steal sample from the stream. + This overload only exists for backwards compatibility it is advised to use this overload only when needed, since the 'other' overload of this method might be faster and more accurate. + Calling this method after you have stopped live recording rendering with has no effect anymore. + + + + private WaveForm WF = null; + private RECORDPROC _myRecProc; // make it global, so that the GC can not remove it + private int _recHandle = 0; + ... + _myRecProc = new RECORDPROC(MyRecording); + _recHandle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, _myRecProc, IntPtr.Zero); + // create a live recording WaveForm + WF = new WaveForm(); + WF.FrameResolution = 0.01f; // 10ms are nice + // start a live recording waveform with 10sec. init size and 5sec. next size + WF.RenderStartRecording(_recHandle, 10, 5); + // really start recording + Bass.BASS_ChannelPlay(_recHandle, false); + ... + // stops recording + Bass.BASS_ChannelStop(_recHandle); + // stop the live recording waveform + if (WF != null) + { + WF.RenderStopRecording(); + DrawWave(); + } + ... + // the recording callback in which we will render the WaveForm + private bool MyRecording(int handle, IntPtr buffer, int length, IntPtr user) + { + if (length > 0 && buffer != IntPtr.Zero) + { + // get and draw our live recording waveform + WF.RenderRecording(buffer, length); + DrawWave(); + } + return true; // always continue recording + } + ... + // draws a rendered WaveForm to a PictureBox + private void DrawWave() + { + if (WF != null) + this.pictureBoxLiveWave.BackgroundImage = WF.CreateBitmap(this.pictureBoxLiveWave.Width, + this.pictureBoxLiveWave.Height, + -1, -1, false); + else + this.pictureBoxLiveWave.BackgroundImage = null; + } + + + Private WF As WaveForm = Nothing + Private _myRecProc As RECORDPROC ' make it global, so that the GC can not remove it + Private _recHandle As Integer = 0 + ... + _myRecProc = New RECORDPROC(AddressOf MyRecording) + _recHandle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, _myRecProc, IntPtr.Zero) + ' create a live recording WaveForm + WF = New WaveForm() + WF.FrameResolution = 0.01F ' 10ms are nice + ' start a live recording waveform with 10sec. init size and 5sec. next size + WF.RenderStartRecording(_recHandle, 10, 5) + ' really start recording + Bass.BASS_ChannelPlay(_recHandle, False) + ... + ' stops recording + Bass.BASS_ChannelStop(_recHandle) + ' stop the live recording waveform + If Not (WF Is Nothing) Then + WF.RenderStopRecording() + DrawWave() + End If + ... + ' the recording callback in which we will render the WaveForm + Private Function MyRecording(handle As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Boolean + If length > 0 AndAlso buffer <> IntPtr.Zero Then + ' get and draw our live recording waveform + WF.RenderRecording(buffer, length) + DrawWave() + End If + Return True ' always continue recording + End Function + + ' draws a rendered WaveForm to a PictureBox + Private Sub DrawWave() + If Not (WF Is Nothing) Then + Me.pictureBoxLiveWave.BackgroundImage = WF.CreateBitmap(Me.pictureBoxLiveWave.Width, + Me.pictureBoxLiveWave.Height, + -1, -1, False) + Else + Me.pictureBoxLiveWave.BackgroundImage = Nothing + End If + End Sub + + + + + + Renders live recorded data and generates the WaveForm data for it. + + The pointer to the sample data to render (e.g. as received within a ). + The length of the data with the buffer. + Call this method subsequently and often enough to get the actual recording data and perform the rendering of that data - typically with a . + You must have started live rendering recording with before calling this method. + You might use the method either within a or any other BASS callback in which you receive sample data (a for example). + Use this overload, if you want to render live sample data even from a decoding stream! + Calling this method after you have stopped live recording rendering with has no effect anymore. + + + + private WaveForm WF = null; + private RECORDPROC _myRecProc; // make it global, so that the GC can not remove it + private int _recHandle = 0; + ... + _myRecProc = new RECORDPROC(MyRecording); + _recHandle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, _myRecProc, IntPtr.Zero); + // create a live recording WaveForm + WF = new WaveForm(); + WF.FrameResolution = 0.01f; // 10ms are nice + // start a live recording waveform with 10sec. init size and 5sec. next size + WF.RenderStartRecording(_recHandle, 10, 5); + // really start recording + Bass.BASS_ChannelPlay(_recHandle, false); + ... + // stops recording + Bass.BASS_ChannelStop(_recHandle); + // stop the live recording waveform + if (WF != null) + { + WF.RenderStopRecording(); + DrawWave(); + } + ... + // the recording callback in which we will render the WaveForm + private bool MyRecording(int handle, IntPtr buffer, int length, IntPtr user) + { + if (length > 0 && buffer != IntPtr.Zero) + { + // get and draw our live recording waveform + WF.RenderRecording(buffer, length); + DrawWave(); + } + return true; // always continue recording + } + + // draws a rendered WaveForm to a PictureBox + private void DrawWave() + { + if (WF != null) + this.pictureBoxLiveWave.BackgroundImage = WF.CreateBitmap(this.pictureBoxLiveWave.Width, + this.pictureBoxLiveWave.Height, + -1, -1, false); + else + this.pictureBoxLiveWave.BackgroundImage = null; + } + + + Private WF As WaveForm = Nothing + Private _myRecProc As RECORDPROC ' make it global, so that the GC can not remove it + Private _recHandle As Integer = 0 + ... + _myRecProc = New RECORDPROC(AddressOf MyRecording) + _recHandle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, _myRecProc, IntPtr.Zero) + ' create a live recording WaveForm + WF = New WaveForm() + WF.FrameResolution = 0.01F ' 10ms are nice + ' start a live recording waveform with 10sec. init size and 5sec. next size + WF.RenderStartRecording(_recHandle, 10, 5) + ' really start recording + Bass.BASS_ChannelPlay(_recHandle, False) + ... + ' stops recording + Bass.BASS_ChannelStop(_recHandle) + ' stop the live recording waveform + If Not (WF Is Nothing) Then + WF.RenderStopRecording() + DrawWave() + End If + ... + ' the recording callback in which we will render the WaveForm + Private Function MyRecording(handle As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Boolean + If length > 0 AndAlso buffer <> IntPtr.Zero Then + ' get and draw our live recording waveform + WF.RenderRecording(buffer, length) + DrawWave() + End If + Return True ' always continue recording + End Function + + ' draws a rendered WaveForm to a PictureBox + Private Sub DrawWave() + If Not (WF Is Nothing) Then + Me.pictureBoxLiveWave.BackgroundImage = WF.CreateBitmap(Me.pictureBoxLiveWave.Width, + Me.pictureBoxLiveWave.Height, + -1, -1, False) + Else + Me.pictureBoxLiveWave.BackgroundImage = Nothing + End If + End Sub + + + + + + Sets a playback channel to synchronize the wave form positions. + + The playback channel which should be used to synchronize the WaveForm position members. + on success - else (e.g. channel is an invalid stream) will be returned. + + If you intend to use the wave form in parallel while already playing out a stream, it is recommended to specify the same flags as for your playing stream (see e.g. ). + This is because , , , etc. would return different values if you specified different resolutions for your playing stream and your rendering stream (eg. a stream with BASS_SAMPLE_FLOAT would return twice as much bytes as a stream created with the default 16-bit resolution). + If your playing stream and and the rendering process uses different flags, you might use this method, so that the members , , and + will return converted values according to your playing stream. + Note: The will be reset to 0% when calling this method! + + + + + Converts a given playback position to the rendering position according to the . + + The playback position (in bytes) to convert. + The converted rendering position. + + + + Converts a given playback position to the rendering position according to the . + + The playback position (in seconds) to convert. + The converted rendering position or -1 on error. + + + + Converts a given rendering position to the playback position according to the . + + The rendering position (in bytes) to convert. + The converted playback position. + + + + Converts a given rendering position to the playback position according to the . + + The rendering position (in seconds) to convert. + The converted playback position or -1 on error. + + + + Converts a given position (in bytes) to the frame number. + + The position (in bytes) which should be translated to a frame number. + The frame number which represents the position. Or -1, if an error occured or the wave form has not been rendered yet. + The wave form must have been rendered already before you can use this method. + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + this method would return the frame according to the rendering process, meaning the position would reflect a different value. + You might use the method to ensure, that the position will automatically be converted accordingly. + + + + + Converts a given position (in seconds) to the frame number. + + The position (in seconds) which should be translated to a frame number. + The frame number which represents the position. Or -1, if an error occured or the wave form has not been rendered yet. + The wave form must have been rendered already before you can use this method. + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + this method would return the frame according to the rendering process, meaning the position would reflect a different value. + You might use the method to ensure, that the position will automatically be converted accordingly. + + + + + Converts a given frame to the position (in bytes). + + The frame number which should be converted. + The position (in bytes) or -1, if an error occured or the wave form has not been rendered yet. + The wave form must have been rendered already before you can use this method. + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + this method would return the frame according to the rendering process, meaning the position would reflect a different value. + You might use the method to ensure, that the position will automatically be converted accordingly. + + + + + Converts a given frame to the position (in seconds). + + The frame number which should be converted. + The position (in seconds) or -1, if an error occured or the wave form has not been rendered yet. + The wave form must have been rendered already before you can use this method. + + + + + Add or replace a marker to the WaveForm. + + The name of the marker to add or replace. + You might specify an optional marker color by adding the following string to the end of the name: "{Color=colorname}" or "{Color=0xhexcolor}" + Example: "My Marker1{Color=Gray}", "My Marker2{Color=0x78FF0000}" + Note: On the CE version of BASS.NET you can only specify a hex color value. + You might specify an optional marker alignment by adding the following string to the end of the name: "{Align=Left|Right|Center|Auto} (the default is Auto)." + Example: "My Marker1{Align=Center}", "My Marker2{Color=0x78FF0000}{Align=Right}" + + The position (in bytes) of the marker (e.g. as returned by ). + , if the marker was added or replaced successfully, else . + Markers might be used to highlight certain positions within a WaveForm, e.g. Cue-, Ramp-, Fade- or Mix-Points. + Use the property to define if and how markers should be drawn within the WaveForm. The property will be used as the the drawing color. + In order to remove a marker use the or methods. + Before adding markers the buffer must have been created. So make sure this method is only called after , or . + Use the method to retrive a certain marker position. To obtain a list of all markers you might use the or methods. + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + adding markers might result in a different position, meaning the position would reflect a different value during playback. + In such case call the method to ensure, that the position will be converted accordingly. + Note: The byte position will be converted to the original rendering resolution according the . + So if your playback stream has a different resolution never add marker positions without first calling . + + + + private Un4seen.Bass.Misc.WaveForm WF = null; + ... + // render a wave form + WF = new WaveForm(_fileName, new WAVEFORMPROC(MyWaveFormCallback), this); + WF.FrameResolution = 0.01f; // 10ms are nice + WF.CallbackFrequency = 500; // every 5 seconds rendered (500*10ms=5sec) + WF.DrawMarker = WaveForm.MARKERDRAWTYPE.Line | + WaveForm.MARKERDRAWTYPE.Name | + WaveForm.MARKERDRAWTYPE.NamePositionAlternate; + // it is important to use the same resolution flags as for the playing stream! + // our already playing stream is 32-bit float - so this one will also need to be... + WF.RenderStart( false, BASSFlag.BASS_SAMPLE_FLOAT ); + // from here on we might add markers...just examples here... + WF.AddMarker( "CueIn", Bass.BASS_ChannelSeconds2Bytes(_stream, 2.0) ); + WF.AddMarker( "RampUp", Bass.BASS_ChannelSeconds2Bytes(_stream, 17.5)); + WF.AddMarker( "Outro", Bass.BASS_ChannelSeconds2Bytes(_stream, 100.7)); + WF.AddMarker( "Mix", Bass.BASS_ChannelSeconds2Bytes(_stream, 130.3)); + WF.AddMarker( "End", Bass.BASS_ChannelSeconds2Bytes(_stream, 136.9)); + ... + // this will replace the 'RampUp' marker + WF.AddMarker( "RampUp", Bass.BASS_ChannelSeconds2Bytes(_stream, 19.2)); + + + Private WF As Un4seen.Bass.Misc.WaveForm = Nothing + ... + ' render a wave form + WF = New WaveForm(_fileName, New WAVEFORMPROC(MyWaveFormCallback), Me) + WF.FrameResolution = 0.01F ' 10ms are nice + WF.CallbackFrequency = 500 ' every 5 seconds rendered (500*10ms=5sec) + WF.DrawMarker = WaveForm.MARKERDRAWTYPE.Line Or + WaveForm.MARKERDRAWTYPE.Name Or + WaveForm.MARKERDRAWTYPE.NamePositionAlternate + ' it is important to use the same resolution flags as for the playing stream! + ' our already playing stream is 32-bit float - so this one will also need to be... + WF.RenderStart(False, BASSFlag.BASS_SAMPLE_FLOAT) + ' from here on we might add markers...just examples here... + WF.AddMarker("CueIn", Bass.BASS_ChannelSeconds2Bytes(_stream, 2.0)) + WF.AddMarker("RampUp", Bass.BASS_ChannelSeconds2Bytes(_stream, 17.5)) + WF.AddMarker("Outro", Bass.BASS_ChannelSeconds2Bytes(_stream, 100.7)) + WF.AddMarker("Mix", Bass.BASS_ChannelSeconds2Bytes(_stream, 130.3)) + WF.AddMarker("End", Bass.BASS_ChannelSeconds2Bytes(_stream, 136.9)) + ... + ' this will replace the 'RampUp' marker + WF.AddMarker("RampUp", Bass.BASS_ChannelSeconds2Bytes(_stream, 19.2)) + + + + + + Add or replace a marker to the WaveForm. + + The name of the marker to add or replace. + You might specify an optional marker color by adding the following string to the end of the name: "{Color=colorname}" or "{Color=0xhexcolor}" + Example: "My Marker1{Color=Gray}", "My Marker2{Color=0x78FF0000}" + Note: On the CE version of BASS.NET you can only specify a hex color value. + You might specify an optional marker alignment by adding the following string to the end of the name: "{Align=Left|Right|Center|Auto} (the default is Auto)." + Example: "My Marker1{Align=Center}", "My Marker2{Color=0x78FF0000}{Align=Right}" + + The position (in seconds) of the marker (e.g. as returned by ). + , if the marker was added or replaced successfully, else . + Markers might be used to highlight certain positions within a WaveForm, e.g. Cue-, Ramp-, Fade- or Mix-Points. + Use the property to define if and how markers should be drawn within the WaveForm. The property will be used as the the drawing color. + In order to remove a marker use the or methods. + Before adding markers the buffer must have been created. So make sure this method is only called after , or . + Use the method to retrive a certain marker position. To obtain a list of all markers you might use the or methods. + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + adding markers might result in a different position, meaning the position would reflect a different value during playback. + In such case call the method to ensure, that the position will be converted accordingly. + Note: The seconds position will be converted to the original rendering resolution according the . + So if your playback stream has a different resolution never add marker positions without first calling . + + + + private Un4seen.Bass.Misc.WaveForm WF = null; + ... + // render a wave form + WF = new WaveForm(_fileName, new WAVEFORMPROC(MyWaveFormCallback), this); + WF.FrameResolution = 0.01f; // 10ms are nice + WF.CallbackFrequency = 500; // every 5 seconds rendered (500*10ms=5sec) + WF.DrawMarker = WaveForm.MARKERDRAWTYPE.Line | + WaveForm.MARKERDRAWTYPE.Name | + WaveForm.MARKERDRAWTYPE.NamePositionAlternate; + // it is important to use the same resolution flags as for the playing stream! + // our already playing stream is 32-bit float - so this one will also need to be... + WF.RenderStart( false, BASSFlag.BASS_SAMPLE_FLOAT ); + // from here on we might add markers...just examples here... + WF.AddMarker( "CueIn", 2.0 ); + WF.AddMarker( "RampUp", 17.5); + WF.AddMarker( "Outro", 100.7); + WF.AddMarker( "Mix", 130.3); + WF.AddMarker( "End", 136.9); + ... + // this will replace the 'RampUp' marker + WF.AddMarker( "RampUp", 19.2); + + + Private WF As Un4seen.Bass.Misc.WaveForm = Nothing + ... + ' render a wave form + WF = New WaveForm(_fileName, New WAVEFORMPROC(MyWaveFormCallback), Me) + WF.FrameResolution = 0.01F ' 10ms are nice + WF.CallbackFrequency = 500 ' every 5 seconds rendered (500*10ms=5sec) + WF.DrawMarker = WaveForm.MARKERDRAWTYPE.Line Or + WaveForm.MARKERDRAWTYPE.Name Or + WaveForm.MARKERDRAWTYPE.NamePositionAlternate + ' it is important to use the same resolution flags as for the playing stream! + ' our already playing stream is 32-bit float - so this one will also need to be... + WF.RenderStart(False, BASSFlag.BASS_SAMPLE_FLOAT) + ' from here on we might add markers...just examples here... + WF.AddMarker("CueIn", 2.0) + WF.AddMarker("RampUp", 17.5) + WF.AddMarker("Outro", 100.7) + WF.AddMarker("Mix", 130.3) + WF.AddMarker("End", 136.9) + ... + ' this will replace the 'RampUp' marker + WF.AddMarker("RampUp", 19.2) + + + + + + Returns a given marker position. + + The name of the marker to get. + The marker position in bytes or -1 if the marker name does not exist. + This is the complementary method of . + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + this method would return the position according to the rendering process, meaning the position would reflect a different value. + In this case make sure to call before getting any markers. This will ensure that the position will be converted accordingly to the playback. + + + + private Un4seen.Bass.Misc.WaveForm WF = null; + ... + // render a wave form + WF = new WaveForm(_fileName, new WAVEFORMPROC(MyWaveFormCallback), this); + WF.FrameResolution = 0.01f; // 10ms are nice + WF.CallbackFrequency = 500; // every 5 seconds rendered (500*10ms=5sec) + WF.DrawMarker = WaveForm.MARKERDRAWTYPE.Line | + WaveForm.MARKERDRAWTYPE.Name | + WaveForm.MARKERDRAWTYPE.NamePositionAlternate; + WF.RenderStart( false, BASSFlag.BASS_SAMPLE_FLOAT ); + // from here on we might add markers...just examples here... + WF.AddMarker( "CueIn", Bass.BASS_ChannelSeconds2Bytes(_stream, 2.0) ); + ... + // this will get the 'CueIn' marker + long position = WF.GetMarker( "CueIn" ); + + + Private WF As Un4seen.Bass.Misc.WaveForm = Nothing + ... + ' render a wave form + WF = New WaveForm(_fileName, New WAVEFORMPROC(MyWaveFormCallback), Me) + WF.FrameResolution = 0.01F ' 10ms are nice + WF.CallbackFrequency = 500 ' every 5 seconds rendered (500*10ms=5sec) + WF.DrawMarker = WaveForm.MARKERDRAWTYPE.Line Or + WaveForm.MARKERDRAWTYPE.Name Or + WaveForm.MARKERDRAWTYPE.NamePositionAlternate + WF.RenderStart(False, BASSFlag.BASS_SAMPLE_FLOAT) + ' from here on we might add markers...just examples here... + WF.AddMarker("CueIn", Bass.BASS_ChannelSeconds2Bytes(_stream, 2.0)) + ... + ' this will get the 'CueIn' marker + Dim position As Long = WF.GetMarker("CueIn") + + + + + + Returns a given marker position. + + The name of the marker to get. + The marker position in seconds or -1 if the marker name does not exist. + This is the complementary method of . + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + this method would return the position according to the rendering process, meaning the position would reflect a different value. + In this case make sure to call before getting any markers. This will ensure that the position will be converted accordingly to the playback. + + + + private Un4seen.Bass.Misc.WaveForm WF = null; + ... + // render a wave form + WF = new WaveForm(_fileName, new WAVEFORMPROC(MyWaveFormCallback), this); + WF.FrameResolution = 0.01f; // 10ms are nice + WF.CallbackFrequency = 500; // every 5 seconds rendered (500*10ms=5sec) + WF.DrawMarker = WaveForm.MARKERDRAWTYPE.Line | + WaveForm.MARKERDRAWTYPE.Name | + WaveForm.MARKERDRAWTYPE.NamePositionAlternate; + WF.RenderStart( false, BASSFlag.BASS_SAMPLE_FLOAT ); + // from here on we might add markers...just examples here... + WF.AddMarker( "CueIn", 2.0 ); + ... + // this will get the 'CueIn' marker + double position = WF.GetMarkerSec( "CueIn" ); + + + Private WF As Un4seen.Bass.Misc.WaveForm = Nothing + ... + ' render a wave form + WF = New WaveForm(_fileName, New WAVEFORMPROC(MyWaveFormCallback), Me) + WF.FrameResolution = 0.01F ' 10ms are nice + WF.CallbackFrequency = 500 ' every 5 seconds rendered (500*10ms=5sec) + WF.DrawMarker = WaveForm.MARKERDRAWTYPE.Line Or + WaveForm.MARKERDRAWTYPE.Name Or + WaveForm.MARKERDRAWTYPE.NamePositionAlternate + WF.RenderStart(False, BASSFlag.BASS_SAMPLE_FLOAT) + ' from here on we might add markers...just examples here... + WF.AddMarker("CueIn", 2.0) + ... + ' this will get the 'CueIn' marker + Dim position As Double = WF.GetMarkerSec("CueIn") + + + + + + Returns the number of markers within the wave form. + + The number of markers present. + You might add new markers with and get existing markers with . + will provide you with a list of marker names. will remove a certain marker from the list and will remove all markers. + + + + + Returns an array of strings containing all marker names. + + A string array with all marker names or an empty array if no markers are present. + You might add new markers with and get existing markers with . + will provide you with the total number of markers present. will remove a certain marker from the list and will remove all markers. + + + + + Removes an existing marker from the WaveForm. + + The name of the marker to remove. + , if the marker was removed successfully, else . + Markers might be used to highlight certain positions within a WaveForm, e.g. Cue-, Ramp-, Fade- or Mix-Points. + Use the property to define if and how markers should be drawn within the WaveForm. The property will be used as the the drawing color. + In order to remove all markers use the method. If you need to add new markers or replace an existing marker use the method. + Before removing markers the buffer must have been created. So make sure this method is only called after , or . + To obtain a list of all markers you might use the dictionary member (Key=name, Value=position) of the property. + + + + private Un4seen.Bass.Misc.WaveForm WF = null; + ... + // render a wave form + WF = new WaveForm(this._fileName, new WAVEFORMPROC(MyWaveFormCallback), this); + WF.DrawMarker = WaveForm.MARKERDRAWTYPE.Line; + WF.RenderStart( true, BASSFlag.BASS_SAMPLE_FLOAT ); + // from here on we might add markers...just examples here... + WF.AddMarker( "CueIn", Bass.BASS_ChannelSeconds2Bytes(_stream, 2.0) ); + WF.AddMarker( "RampUp", Bass.BASS_ChannelSeconds2Bytes(_stream, 17.5)); + WF.AddMarker( "Outro", Bass.BASS_ChannelSeconds2Bytes(_stream, 100.7)); + WF.AddMarker( "Mix", Bass.BASS_ChannelSeconds2Bytes(_stream, 130.3)); + WF.AddMarker( "End", Bass.BASS_ChannelSeconds2Bytes(_stream, 136.9)); + ... + // this will remove the 'CueIn' marker + WF.RemoveMarker( "CueIn" ); + + + Private WF As Un4seen.Bass.Misc.WaveForm = Nothing + ... + ' render a wave form + WF = New WaveForm(Me._fileName, New WAVEFORMPROC(MyWaveFormCallback), Me) + WF.DrawMarker = WaveForm.MARKERDRAWTYPE.Line + WF.RenderStart(True, BASSFlag.BASS_SAMPLE_FLOAT) + ' from here on we might add markers...just examples here... + WF.AddMarker("CueIn", Bass.BASS_ChannelSeconds2Bytes(_stream, 2.0)) + WF.AddMarker("RampUp", Bass.BASS_ChannelSeconds2Bytes(_stream, 17.5)) + WF.AddMarker("Outro", Bass.BASS_ChannelSeconds2Bytes(_stream, 100.7)) + WF.AddMarker("Mix", Bass.BASS_ChannelSeconds2Bytes(_stream, 130.3)) + WF.AddMarker("End", Bass.BASS_ChannelSeconds2Bytes(_stream, 136.9)) + ... + ' this will remove the 'CueIn' marker + WF.RemoveMarker("CueIn") + + + + + + Removes all markers from the WaveForm. + + on success, else . + Markers might be used to highlight certain positions within a WaveForm, e.g. Cue-, Ramp-, Fade- or Mix-Points. + Use the property to define if and how markers should be drawn within the WaveForm. The property will be used as the the drawing color. + In order to remove all markers use the method. If you need to add new markers or replace an existing marker use the method. + Before removing markers the buffer must have been created. So make sure this method is only called after , or . + To obtain a list of all markers you might use the dictionary member (Key=name, Value=position) of the property. + + + + + Searches for a certain volume point. + + The position (in bytes) of the volume point to search. + If the position is present the zero-based index will be returned; otherwise, a negative number, which is the bitwise complement of the index of the next element that is larger than value or, if there is no larger element, the bitwise complement of Count. + + // return the exact or next volume point + int startIdx = wf.SearchVolumePoint(pos); + if (startIdx < 0) + startIdx = ~startIdx; + + + + + Searches for a certain volume point. + + The position (in seconds) of the volume point to search. + If the position is present the zero-based index will be returned; otherwise, a negative number, which is the bitwise complement of the index of the next element that is larger than value or, if there is no larger element, the bitwise complement of Count. + + // return the exact or next volume point + int startIdx = wf.SearchVolumePoint(pos); + if (startIdx < 0) + startIdx = ~startIdx; + + + + + Searches for a certain volume point. + + The position (in bytes) of the volume point to search. + The previous or exact VolumePoint at the requested position. + The next VolumePoint at the requested position or , if no next point exists. + If the position is present the zero-based index will be returned; otherwise, a negative number, which is the bitwise complement of the index of the next element that is larger than value or, if there is no larger element, the bitwise complement of Count. + + + + Searches for a certain volume point. + + The position (in seconds) of the volume point to search. + The previous or exact VolumePoint at the requested position. + The next VolumePoint at the requested position or , if no next point exists. + If the position is present the zero-based index will be returned; otherwise, a negative number, which is the bitwise complement of the index of the next element that is larger than value or, if there is no larger element, the bitwise complement of Count. + + + + Add or replace a volume point to the WaveForm. + + The position (in bytes) of the volume point (e.g. as returned by ). + The volume level of the point to add or replace (0=silent, 1.0=maximum=0dB). + , if the volume point was added or replaced successfully, else . + Volume points might be used to draw a volume curve within a WaveForm. + Use the property to define if and how the volume curve should be drawn within the WaveForm. The property will be used as the the drawing color. + In order to remove a volume point use the or methods. + Before adding a volume point the buffer must have been created. So make sure this method is only called after , or . + Use the method to retrive a certain volume point. Via you might retrieve the volume level of the curve at any point. + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + adding volume points might result in a different position, meaning the position would reflect a different value during playback. + In such case call the method to ensure, that the position will be converted accordingly. + Note: The byte position will be converted to the original rendering resolution according the . + So if your playback stream has a different resolution never add volume points without first calling . + + + + + Add or replace a volume point to the WaveForm. + + The position (in seconds) of the volume point (e.g. as returned by converted to seconds). + The volume level of the point to add or replace (0=silent, 1.0=maximum=0dB). + , if the volume point was added or replaced successfully, else . + Volume points might be used to draw a volume curve within a WaveForm. + Use the property to define if and how the volume curve should be drawn within the WaveForm. The property will be used as the the drawing color. + In order to remove a volume point use the or methods. + Before adding a volume point the buffer must have been created. So make sure this method is only called after , or . + Use the method to retrive a certain volume point. Via you might retrieve the volume level of the curve at any point. + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + adding volume points might result in a different position, meaning the position would reflect a different value during playback. + In such case call the method to ensure, that the position will be converted accordingly. + Note: The byte position will be converted to the original rendering resolution according the . + So if your playback stream has a different resolution never add volume points without first calling . + + + + + Returns the level of a given volume point. + + The position (in bytes) of the volume point to get. + The level of the volume point (0=silent, 1.0=maximum=0dB) or -1 if the volume points does not exist. + This is the complementary method of . + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + this method would return the position according to the rendering process, meaning the position would reflect a different value. + In this case make sure to call before getting any markers. This will ensure that the position will be converted accordingly. + + + + + Returns the level of a given volume point. + + The position (in seconds) of the volume point to get. + The level of the volume point (0=silent, 1.0=maximum=0dB) or -1 if the volume points does not exist. + This is the complementary method of . + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + this method would return the position according to the rendering process, meaning the position would reflect a different value. + In this case make sure to call before getting any markers. This will ensure that the position will be converted accordingly. + + + + + Returns a certain volume point at the given index. + + The index of the volume point to get. + The volume point at the given index - or if the index is not present. + Use to get the total number of volume points present. + + + + Returns the volume level at the given position of the volume curve. + + The position (in bytes) of the volume point to get. + , if to search in reverse direction - else . + Returns the duration (in bytes) to the next volume point in bytes. + Returns the volume level at the next volume point. + The volume level (0=silent, 1.0=maximum=0dB) at the given position. + Note: This method always returns a volume level, even if the position does not reflect a volume point. In such case the volume level of the volume curve at this position will be returned. + If no volume points have been defined at all this method will return 1. + + + + Returns the volume level at the given position of the volume curve. + + The position (in seconds) of the volume point to get. + , if to search in reverse direction - else . + Returns the duration (in seconds) to the next volume point in bytes. + Returns the volume level at the next volume point. + The volume level (0=silent, 1.0=maximum=0dB) at the given position. + Note: This method always returns a volume level, even if the position does not reflect a volume point. In such case the volume level of the volume curve at this position will be returned. + If no volume points have been defined at all this method will return 1. + + + + Returns the number of volume points within the wave form. + + The number of volume points present. + You might add new volume points with and get existing volume points with or return the volume level at any point via . + will provide you with a list of volume points. will remove a certain volume point from the list and will remove all volume points. + + + + + Removes an existing volume point from the WaveForm. + + The position (in bytes) of the volume point to remove. + , if the volume point was removed successfully, else . + Volume points might be used to draw a volume curve within a WaveForm. + Use the property to define if and how the volume curve should be drawn within the WaveForm. The property will be used as the the drawing color. + In order to remove a volume point use the or methods. + Before adding a volume point the buffer must have been created. So make sure this method is only called after , or . + Use the method to retrive a certain volume point. To get the volume level at any given position of the volume curve use the method. + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + adding volume points might result in a different position, meaning the position would reflect a different value during playback. + In such case call the method to ensure, that the position will be converted accordingly. + Note: The byte position will be converted to the original rendering resolution according the . + So if your playback stream has a different resolution never add volume points without first calling . + + + + + Removes an existing volume point from the WaveForm. + + The position (in seconds) of the volume point to remove. + , if the volume point was removed successfully, else . + Volume points might be used to draw a volume curve within a WaveForm. + Use the property to define if and how the volume curve should be drawn within the WaveForm. The property will be used as the the drawing color. + In order to remove a volume point use the or methods. + Before adding a volume point the buffer must have been created. So make sure this method is only called after , or . + Use the method to retrive a certain volume point. To get the volume level at any given position of the volume curve use the method. + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + adding volume points might result in a different position, meaning the position would reflect a different value during playback. + In such case call the method to ensure, that the position will be converted accordingly. + Note: The byte position will be converted to the original rendering resolution according the . + So if your playback stream has a different resolution never add volume points without first calling . + + + + + Removes all volume points between the two given points exclusive. + + The volume point position (in bytes) from which to remove (exclusive, this point is not removed). + The volume point position (in bytes) to which to remove (exclusive, this point is not removed). + + + + Removes all volume points between the two given points exclusive. + + The volume point position (in seconds) from which to remove (exclusive, this point is not removed). + The volume point position (in seconds) to which to remove (exclusive, this point is not removed). + + + + Removes all volume points from the WaveForm. + + on success, else . + Volume points might be used to draw a volume curve within a WaveForm. + Use the property to define if and how volume points should be drawn within the WaveForm. The property will be used as the the drawing color. + In order to remove all volume points use the method. If you need to add new volume points or replace an existing volume point use the method. + + + + + Creates a bitmap from a rendered wave form. + + The width (in pixel) of the image to create. + The height (in pixel) of the image to create. + The rendered frame from where to start creating the image (specify 0 or -1 to start from the beginning). + The rendered frame til where to creating the image (specify -1 to create til the end). This value must be greater than frameStart. + , if anti alias should be used when drawing. will draw in high speed mode. + The created bitmap image representing the wave form. + + + private Un4seen.Bass.Misc.WaveForm WF = null; + + private void GetWaveForm() + { + // render a wave form + WF = new Un4seen.Bass.Misc.WaveForm("test.mp3", + new Un4seen.Bass.Misc.WAVEFORMPROC(MyWaveFormCallback), this); + WF.CallbackFrequency = 500; // every 10 seconds rendered + WF.ColorBackground = Color.Black; + WF.ColorBase = Color.Lime; + WF.ColorPeak = Color.Red; + // it is important to use the same resolution flags as for the playing stream + // e.g. if an already playing stream is 32-bit float, so this should also be + // or use 'SyncPlayback' as shown below + WF.RenderStart(true, BASSFlag.BASS_DEFAULT); + } + + private void MyWaveFormCallback(int framesDone, int framesTotal, TimeSpan elapsedTime, bool finished) + { + // will be called during rendering... + DrawWave(); + if (finished) + { + Console.WriteLine("Finished rendering in {0}sec.", elapsedTime); + Console.WriteLine("FramesRendered={0} of {1}", WF.FramesRendered, WF.FramesToRender); + // if your playback stream uses a different resolution than the WF + // use this to sync them + WF.SyncPlayback(_stream); + } + } + + private void DrawWave() + { + if (WF != null) + this.pictureBox1.BackgroundImage = WF.CreateBitmap(this.pictureBox1.Width, + this.pictureBox1.Height, + -1, -1, false); + else + this.pictureBox1.BackgroundImage = null; + } + + + Private WF As Un4seen.Bass.Misc.WaveForm = Nothing + ... + Private Sub GetWaveForm() + ' render a wave form + WF = New Un4seen.Bass.Misc.WaveForm("test.mp3", New Un4seen.Bass.Misc.WAVEFORMPROC(MyWaveFormCallback), Me) + WF.CallbackFrequency = 500 ' every 10 seconds rendered + WF.ColorBackground = Color.Black + WF.ColorBase = Color.Lime + WF.ColorPeak = Color.Red + ' it is important to use the same resolution flags as for the playing stream + ' e.g. if an already playing stream is 32-bit float, so this should also be + ' or use 'SyncPlayback' as shown below + WF.RenderStart(True, BASSFlag.BASS_SAMPLE_FLOAT) + End Sub + + Private Sub MyWaveFormCallback(framesDone As Integer, framesTotal As Integer, + elapsedTime As TimeSpan, finished As Boolean) + ' will be called during rendering... + DrawWave() + If finished Then + Console.WriteLine("Finished rendering in {0}sec.", elapsedTime) + Console.WriteLine("FramesRendered={0} of {1}", WF.FramesRendered, WF.FramesToRender) + ' if your playback stream uses a different resolution than the WF + ' use this to sync them + WF.SyncPlayback(_stream) + End If + End Sub + + Private Sub DrawWave() + If Not (WF Is Nothing) Then + Me.pictureBox1.BackgroundImage = WF.CreateBitmap(Me.pictureBox1.Width, + Me.pictureBox1.Height, + -1, -1, False) + Else + Me.pictureBox1.BackgroundImage = Nothing + End If + End Sub + + + + + + Draws the rendered wave form directly on the provided GDI+ graphics. + + The GDI+ graphics object where to draw the wave form (ie. can be taken directly from a ). + The rectangle describing the size of the wave form to draw (ie. can be taken directly from a ). + The rendered frame from where to start creating the image (specify 0 or -1 to start from the beginning). + The rendered frame til where to creating the image (specify -1 to create til the end). + , if anti alias should be used when drawing. will draw in high speed mode. + , if successfully painted, else . + This overload is most useful when you are developing your own custom control. You might use it directly within your paint overload implementation. + + + + Translates a X coordinate of a drawn WaveForm graphic to the related byte position within the rendered stream. + + The X coordinate from which to get the byte position (between 0 and graphicsWidth-1). + The total width of the drawn WaveForm graphic (e.g. use pictureBox.Width). + The rendered frame which was used to start creating the image (specify 0 or -1 if the start was from the beginning). + The rendered frame which was used to end creating the image (specify -1 for the end of the WaveForm). + The converted byte position of the stream which relates to the given X coordinate, else -1. + This method might be used to translate a graphics coordinate to a byte position within a stream. The return value might for example be used by to set a new playback position. + Note: The byte position relates to the resolution you used with ! + So if you for example used the BASS_SAMPLE_FLOAT with the byte position relates to 32-bit sample data. + However, if your playing stream uses only a 16-bit resolution (e.g. you used BASS_DEFAULT with ), the returned byte position will not match! + So make sure when you are calling with this return value, that your stream resolution is the same as the resolution used with . + Otherwise you must convert the returned byte position (e.g. from 32-bit to 16-bit: pos = returnvalue/2). + Or for ease of use you might use the method to ensure, that the return value of this method will already be converted accordingly for you! + + + + Using a pictureBox and the MouseDown event handler: + + // assuming the WaveForm is fully displayed in the pictureBox... + private void DrawWave() + { + if (WF != null) + this.pictureBox1.BackgroundImage = WF.CreateBitmap(this.pictureBox1.Width, + this.pictureBox1.Height, + -1, -1, false); + else + this.pictureBox1.BackgroundImage = null; + } + + private void pictureBox1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) + { + if (WF == null) + return; + long pos = WF.GetBytePositionFromX(e.X, this.pictureBox1.Width, -1, -1); + Console.WriteLine("Position = {0}, Seconds = {1}", pos, Bass.BASS_ChannelBytes2Seconds(_stream, pos)); + Bass.BASS_ChannelSetPosition(_stream, pos); + } + + + ' assuming the WaveForm is fully displayed in the pictureBox... + Private Sub DrawWave() + If Not (WF Is Nothing) Then + Me.pictureBox1.BackgroundImage = WF.CreateBitmap(Me.pictureBox1.Width, + Me.pictureBox1.Height, + -1, -1, False) + Else + Me.pictureBox1.BackgroundImage = Nothing + End If + End Sub + + Private Sub pictureBox1_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) + If WF Is Nothing Then + Return + End If + Dim pos As Long = WF.GetBytePositionFromX(e.X, Me.pictureBox1.Width, - 1, - 1) + Console.WriteLine("Position = {0}, Seconds = {1}", pos, Bass.BASS_ChannelBytes2Seconds(_stream, pos)) + Bass.BASS_ChannelSetPosition(_stream, pos) + End Sub + + + + + + Determines silence positions at the beginning and end of a rendered wave form. + + Returns the position in bytes where the sound begins (cue-in position). + Returns the position in bytes where the sound ends (cue-out position). + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the beginning and end of the track. + on success, else . + + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + getting the cue points might result in different positions, meaning the positions would reflect a different value during playback. + But if you called the method this will ensure, that the position will be converted accordingly. + + + + long startpos = 0; + long endpos = 0; + WF.GetCuePoints(ref startpos, ref endpos, -30.0); + WF.AddMarker( "CUE", startpos ); + WF.AddMarker( "END", endpos ); + ... + + + Dim startpos As Long = 0 + Dim endpos As Long = 0 + WF.GetCuePoints(startpos, endpos, -30.0) + WF.AddMarker("CUE", startpos) + WF.AddMarker("END", endpos) + ... + + + + + + Determines silence positions at the beginning and end of a rendered wave form. + + Returns the position in bytes where the sound begins (cue-in position). + Returns the position in bytes where the sound ends (cue-out position). + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the beginning of the track. + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the end of the track. + on success, else . + + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + getting the cue points might result in different positions, meaning the positions would reflect a different value during playback. + But if you called the method this will ensure, that the position will be converted accordingly. + + + + long startpos = 0; + long endpos = 0; + WF.GetCuePoints(ref startpos, ref endpos, -30.0, -50.0); + WF.AddMarker( "CUE", startpos ); + WF.AddMarker( "END", endpos ); + ... + + + Dim startpos As Long = 0 + Dim endpos As Long = 0 + WF.GetCuePoints(startpos, endpos, -30.0, -50.0) + WF.AddMarker("CUE", startpos) + WF.AddMarker("END", endpos) + ... + + + + + + Determines silence positions of a rendered wave form within a given range. + + Returns the position in bytes where the sound begins (cue-in position). + Returns the position in bytes where the sound ends (cue-out position). + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the beginning of the track. + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the end of the track. + If set to the cue points will be adjusted to the next resp. previous zero crossing in order to avoid clicks (if set to the cue points will be adjusted to a quiter sample only). + on success, else . + + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + getting the cue points might result in different positions, meaning the positions would reflect a different value during playback. + But if you called the method this will ensure, that the position will be converted accordingly. + + + + long startpos = 0; + long endpos = 0; + WF.GetCuePoints(ref startpos, ref endpos, -24.0, -42.0, true); + WF.AddMarker( "CUE", startpos ); + WF.AddMarker( "END", endpos ); + ... + + + Dim startpos As Long = 0 + Dim endpos As Long = 0 + WF.GetCuePoints(startpos, endpos, -24.0, -42.0, True) + WF.AddMarker("CUE", startpos) + WF.AddMarker("END", endpos) + ... + + + + + + Determines silence positions of a rendered wave form within a given range. + + Returns the position in bytes where the sound begins (cue-in position). + Returns the position in bytes where the sound ends (cue-out position). + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the beginning and end of the track. + The frame position where to start the silence detection (between 0 and , or -1 to scan from the beginning). + The frame position til where to perform the silence detection (between 0 and , or -1 to scan til the end; must be bigger than frameStart). + on success, else . + + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + getting the cue points might result in different positions, meaning the positions would reflect a different value during playback. + But if you called the method this will ensure, that the position will be converted accordingly. + + + + long startpos = 0; + long endpos = 0; + WF.GetCuePoints(ref startpos, ref endpos, -40.0, -1, -1); + WF.AddMarker( "CUE", startpos ); + WF.AddMarker( "END", endpos ); + ... + + + Dim startpos As Long = 0 + Dim endpos As Long = 0 + WF.GetCuePoints(startpos, endpos, -40.0, -1, -1) + WF.AddMarker("CUE", startpos) + WF.AddMarker("END", endpos) + ... + + + + + + Determines silence positions of a rendered wave form within a given range. + + Returns the position in bytes where the sound begins (cue-in position). + Returns the position in bytes where the sound ends (cue-out position). + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the beginning and end of the track. + The frame position where to start the silence detection (between 0 and , or -1 to scan from the beginning). + The frame position til where to perform the silence detection (between 0 and , or -1 to scan til the end; must be bigger than frameStart). + If set to the cue points will be adjusted to the next resp. previous zero crossing in order to avoid clicks (if set to the cue points will be adjusted to a quiter sample only). + on success, else . + + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + getting the cue points might result in different positions, meaning the positions would reflect a different value during playback. + But if you called the method this will ensure, that the position will be converted accordingly. + + + + long startpos = 0; + long endpos = 0; + WF.GetCuePoints(ref startpos, ref endpos, -42.0, -1, -1, true); + WF.AddMarker( "CUE", startpos ); + WF.AddMarker( "END", endpos ); + ... + + + Dim startpos As Long = 0 + Dim endpos As Long = 0 + WF.GetCuePoints(startpos, endpos, -42.0, -1, -1, True) + WF.AddMarker("CUE", startpos) + WF.AddMarker("END", endpos) + ... + + + + + + Determines silence positions of a rendered wave form within a given range. + + Returns the position in bytes where the sound begins (cue-in position). + Returns the position in bytes where the sound ends (cue-out position). + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the beginning of the track. + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the end of the track. + The frame position where to start the silence detection (between 0 and , or -1 to scan from the beginning). + The frame position til where to perform the silence detection (between 0 and , or -1 to scan til the end; must be bigger than frameStart). + on success, else . + + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + getting the cue points might result in different positions, meaning the positions would reflect a different value during playback. + But if you called the method this will ensure, that the position will be converted accordingly. + + + + long startpos = 0; + long endpos = 0; + WF.GetCuePoints(ref startpos, ref endpos, -24.0, -50.0, -1, -1); + WF.AddMarker( "CUE", startpos ); + WF.AddMarker( "END", endpos ); + ... + + + + + + Determines silence positions of a rendered wave form within a given range. + + Returns the position in bytes where the sound begins (cue-in position). + Returns the position in bytes where the sound ends (cue-out position). + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the beginning of the track. + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the end of the track. + The frame position where to start the silence detection (between 0 and , or -1 to scan from the beginning). + The frame position til where to perform the silence detection (between 0 and , or -1 to scan til the end; must be bigger than frameStart). + If set to the cue points will be adjusted to the next resp. previous zero crossing in order to avoid clicks (if set to the cue points will be adjusted to a quiter sample only). + on success, else . + + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + getting the cue points might result in different positions, meaning the positions would reflect a different value during playback. + But if you called the method this will ensure, that the position will be converted accordingly. + + + + long startpos = 0; + long endpos = 0; + WF.GetCuePoints(ref startpos, ref endpos, -30.0, -50.0, -1, -1, true); + WF.AddMarker( "CUE", startpos ); + WF.AddMarker( "END", endpos ); + ... + + + Dim startpos As Long = 0 + Dim endpos As Long = 0 + WF.GetCuePoints(startpos, endpos, -30.0, -50.0, -1, -1, True) + WF.AddMarker("CUE", startpos) + WF.AddMarker("END", endpos) + ... + + + + + + Determines silence positions at the beginning and end of a rendered wave form. + + Returns the position in seconds where the sound begins (cue-in position). + Returns the position in seconds where the sound ends (cue-out position). + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the beginning and end of the track. + on success, else . + + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + getting the cue points might result in different positions, meaning the positions would reflect a different value during playback. + But if you called the method this will ensure, that the position will be converted accordingly. + + + + double startpos = 0.0; + double endpos = 0.0; + WF.GetCuePoints(ref startpos, ref endpos, -30.0); + WF.AddMarker( "CUE", startpos ); + WF.AddMarker( "END", endpos ); + ... + + + Dim startpos As Double = 0.0 + Dim endpos As Double = 0.0 + WF.GetCuePoints(startpos, endpos, -30.0) + WF.AddMarker("CUE", startpos) + WF.AddMarker("END", endpos) + ... + + + + + + Determines silence positions at the beginning and end of a rendered wave form. + + Returns the position in seconds where the sound begins (cue-in position). + Returns the position in seconds where the sound ends (cue-out position). + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the beginning of the track. + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the end of the track. + on success, else . + + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + getting the cue points might result in different positions, meaning the positions would reflect a different value during playback. + But if you called the method this will ensure, that the position will be converted accordingly. + + + + double startpos = 0.0; + double endpos = 0.0; + WF.GetCuePoints(ref startpos, ref endpos, -30.0, -50.0); + WF.AddMarker( "CUE", startpos ); + WF.AddMarker( "END", endpos ); + ... + + + Dim startpos As Double = 0.0 + Dim endpos As Double = 0.0 + WF.GetCuePoints(startpos, endpos, -30.0, -50.0) + WF.AddMarker("CUE", startpos) + WF.AddMarker("END", endpos) + ... + + + + + + Determines silence positions of a rendered wave form within a given range. + + Returns the position in seconds where the sound begins (cue-in position). + Returns the position in seconds where the sound ends (cue-out position). + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the beginning of the track. + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the end of the track. + If set to the cue points will be adjusted to the next resp. previous zero crossing in order to avoid clicks (if set to the cue points will be adjusted to a quiter sample only). + on success, else . + + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + getting the cue points might result in different positions, meaning the positions would reflect a different value during playback. + But if you called the method this will ensure, that the position will be converted accordingly. + + + + double startpos = 0.0; + double endpos = 0.0; + WF.GetCuePoints(ref startpos, ref endpos, -24.0, -42.0, true); + WF.AddMarker( "CUE", startpos ); + WF.AddMarker( "END", endpos ); + ... + + + Dim startpos As Double = 0.0 + Dim endpos As Double = 0.0 + WF.GetCuePoints(startpos, endpos, -24.0, -42.0, True) + WF.AddMarker("CUE", startpos) + WF.AddMarker("END", endpos) + ... + + + + + + Determines silence positions of a rendered wave form within a given range. + + Returns the position in seconds where the sound begins (cue-in position). + Returns the position in seconds where the sound ends (cue-out position). + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the beginning and end of the track. + The frame position where to start the silence detection (between 0 and , or -1 to scan from the beginning). + The frame position til where to perform the silence detection (between 0 and , or -1 to scan til the end; must be bigger than frameStart). + on success, else . + + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + getting the cue points might result in different positions, meaning the positions would reflect a different value during playback. + But if you called the method this will ensure, that the position will be converted accordingly. + + + + double startpos = 0.0; + double endpos = 0.0; + WF.GetCuePoints(ref startpos, ref endpos, -40.0, -1, -1); + WF.AddMarker( "CUE", startpos ); + WF.AddMarker( "END", endpos ); + ... + + + Dim startpos As Double = 0.0 + Dim endpos As Double = 0.0 + WF.GetCuePoints(startpos, endpos, -40.0, -1, -1) + WF.AddMarker("CUE", startpos) + WF.AddMarker("END", endpos) + ... + + + + + + Determines silence positions of a rendered wave form within a given range. + + Returns the position in seconds where the sound begins (cue-in position). + Returns the position in seconds where the sound ends (cue-out position). + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the beginning and end of the track. + The frame position where to start the silence detection (between 0 and , or -1 to scan from the beginning). + The frame position til where to perform the silence detection (between 0 and , or -1 to scan til the end; must be bigger than frameStart). + If set to the cue points will be adjusted to the next resp. previous zero crossing in order to avoid clicks (if set to the cue points will be adjusted to a quiter sample only). + on success, else . + + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + getting the cue points might result in different positions, meaning the positions would reflect a different value during playback. + But if you called the method this will ensure, that the position will be converted accordingly. + + + + double startpos = 0.0; + double endpos = 0.0; + WF.GetCuePoints(ref startpos, ref endpos, -42.0, -1, -1, true); + WF.AddMarker( "CUE", startpos ); + WF.AddMarker( "END", endpos ); + ... + + + Dim startpos As Double = 0.0 + Dim endpos As Double = 0.0 + WF.GetCuePoints(startpos, endpos, -42.0, -1, -1, True) + WF.AddMarker("CUE", startpos) + WF.AddMarker("END", endpos) + ... + + + + + + Determines silence positions of a rendered wave form within a given range. + + Returns the position in seconds where the sound begins (cue-in position). + Returns the position in seconds where the sound ends (cue-out position). + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the beginning of the track. + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the end of the track. + The frame position where to start the silence detection (between 0 and , or -1 to scan from the beginning). + The frame position til where to perform the silence detection (between 0 and , or -1 to scan til the end; must be bigger than frameStart). + on success, else . + + If your rendering method and your playback stream used different flags during creation (e.g. rendering was done using the BASS_DEFAULT flag whereas your playback stream uses BASS_SAMPLE_FLOAT) + getting the cue points might result in different positions, meaning the positions would reflect a different value during playback. + But if you called the method this will ensure, that the position will be converted accordingly. + + + + double startpos = 0.0; + double endpos = 0.0; + WF.GetCuePoints(ref startpos, ref endpos, -24.0, -50.0, -1, -1); + WF.AddMarker( "CUE", startpos ); + WF.AddMarker( "END", endpos ); + ... + + + Dim startpos As Double = 0.0 + Dim endpos As Double = 0.0 + WF.GetCuePoints(startpos, endpos, -24.0, -50.0, -1, -1) + WF.AddMarker("CUE", startpos) + WF.AddMarker("END", endpos) + ... + + + + + + Determines silence positions of a rendered wave form within a given range. + + Returns the position in seconds where the sound begins (cue-in position). + Returns the position in seconds where the sound ends (cue-out position). + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the beginning of the track. + The threshold in dB (e.g. -24.0dB) which should be used to detect silence resp. sound at the end of the track. + The frame position where to start the silence detection (between 0 and , or -1 to scan from the beginning). + The frame position til where to perform the silence detection (between 0 and , or -1 to scan til the end; must be bigger than frameStart). + If set to the cue points will be adjusted to the next resp. previous zero crossing in order to avoid clicks (if set to the cue points will be adjusted to a quiter sample only). + on success, else . + + + double startpos = 0.0; + double endpos = 0.0; + WF.GetCuePoints(ref startpos, ref endpos, -30.0, -50.0, -1, -1, true); + WF.AddMarker( "CUE", startpos ); + WF.AddMarker( "END", endpos ); + ... + + + Dim startpos As Double = 0.0 + Dim endpos As Double = 0.0 + WF.GetCuePoints(startpos, endpos, -30.0, -50.0, -1, -1, True) + WF.AddMarker("CUE", startpos) + WF.AddMarker("END", endpos) + ... + + + + + + Determines a gain factor (normalization), so that the maximum peak level of the sample data will be at 0 dB. + + The frame position where to start the calculation (between 0 and , or -1 to scan from the beginning). + The frame position til where to perform the calculation (between 0 and , or -1 to scan til the end; must be bigger than frameStart). + Returns the maximum peak level as a float value between 0.0 (silence) and 1.0 (0dB). + The gain factor as a float value. + + You might use the gain factor as a multiplier to the sample data to apply a volume adjustment, so that the maximum peak level of the audio samples is at 0 dB. + + + + + Finds the next position with a certain volume level. + + The position in bytes where to start the search. + The threshold in dB (e.g. -12.0dB) which should be searched. + Search forward () or backward (). + If set to the returned position will be adjusted to the next resp. previous zero crossing in order to avoid clicks. + The position with the respective volume level (if the level could not be detected, then startpos will be returned). + + + + Finds the next position with a certain volume level. + + The position in seconds where to start the search. + The threshold in dB (e.g. -12.0dB) which should be searched. + Search forward () or backward (). + If set to the returned position will be adjusted to the next resp. previous zero crossing in order to avoid clicks. + The position with the respective volume level (if the level could not be detected, then startpos will be returned). + + + + Finds the previous zero crossing position related to the given position (backward seeking). + + The position where to start the search. + The previous zero crossing position. + If the given position already denotes a zero-crossing position the same position will be returned. + + + + Finds the next zero crossing position related to the given position (forward seeking). + + The position where to start the search. + The next zero crossing position. + /// If the given position already denotes a zero-crossing position the same position will be returned. + + + + Returns the peak level (between 0 and 32767) of a given frame position. + + The frame position (between 0 and ) to get the peak level from. + The peak level between 0 and 32767 of the given position. + + + + Detects, if the two given positions reflect a zero crossing. + + The frame position1 (between 0 and ) to check for zero crossing. + The frame position2 (between 0 and ) to check for zero crossing. + , if the given positions denote a crossing of a zero level of either the left or right channel - else . + + + + Performs the actual rendering. + + = in background thread. + The thread priority to be used with the background thread (default is BelowNormal). + The stream create flags. + The number of channels (1=mono, 2=stereo, etc.) + = successfully started/executed. + + + + Does the actual scanning of the peak levels + + + + + Calls the notification handler. + + , if the render process has finished. + + + + Internal method to draw the actual wave form. + + The graphics object where to draw. + width to draw + height to draw + starting frame + ending frame + + + pen left + pen left + pen right + pen right + pen marker + pen beat + pen volume + + + + Saves a rendered WaveForm to a file (uncompressed). + + The file name to save the rendered data to. + on success, else . + Writes the WaveForm to a file using standard serialization. + + + + Saves a rendered WaveForm to a file. + + The file name to save the rendered data to. + If the WaveForm will be saved to a binary - else standard serialization will be carried out. + on success, else . + The binary format is much more compact and faster, so it is advised to use this format. + Note, that you must load the WaveForm using the save format as it was saved. + + + + Saves a rendered WaveForm to a byte array. + + The byte array containing the serialized data of the wave form. + Writes the WaveForm to a byte array using standard serialization. + + + private byte[] waveformSave; + ... + // save the wave form to a byte array + waveformSave = WF.WaveFormSaveToMemory(); + .. + // load the wave form to a byte array + WF = new Un4seen.Bass.Misc.WaveForm(); + WF.WaveFormLoadFromMemory( waveformSave ); + WF.DrawMarker = WaveForm.MARKERDRAWTYPE.Line | WaveForm.MARKERDRAWTYPE.Name | WaveForm.MARKERDRAWTYPE.NamePositionAlternate; + this.pictureBox1.BackgroundImage = WF.CreateBitmap( this.pictureBox1.Width, this.pictureBox1.Height, -1, -1, true); + + + + + + Saves a rendered WaveForm to a byte array. + + If the WaveForm will be saved in binary format - else standard serialization will be carried out. + The byte array containing the serialized data of the wave form. + The binary format is much more compact and faster, so it is advised to use this format. + Note, that you must load the WaveForm using the save format as it was saved. + + + private byte[] waveformSave; + ... + // save the wave form to a byte array + waveformSave = WF.WaveFormSaveToMemory(true); + .. + // load the wave form to a byte array + WF = new Un4seen.Bass.Misc.WaveForm(); + WF.WaveFormLoadFromMemory( waveformSave, true ); + WF.DrawMarker = WaveForm.MARKERDRAWTYPE.Line | WaveForm.MARKERDRAWTYPE.Name | WaveForm.MARKERDRAWTYPE.NamePositionAlternate; + this.pictureBox1.BackgroundImage = WF.CreateBitmap( this.pictureBox1.Width, this.pictureBox1.Height, -1, -1, true); + + + + + + Loads a rendered WaveForm from a file. + + The file name to load the rendered data from. + on success, else . + Loads the WaveForm using standard serialization. + + + + Loads a rendered WaveForm from a file. + + The file name to load the rendered data from. + If the WaveForm will be loaded from a binary - else standard deserialization will be carried out. + on success, else . + The binary format is much more compact and faster, so it is advised to use this format. + Note, that you must load the WaveForm in the same format as it was saved. + + + + Loads a rendered WaveForm from a byte array. + + The byte array to load the rendered data from (e.g. created with ). + on success, else . + Loads the WaveForm using standard serialization. + + + private byte[] waveformSave; + ... + // save the wave form to a byte array + waveformSave = WF.WaveFormSaveToMemory(); + .. + // load the wave form to a byte array + WF = new Un4seen.Bass.Misc.WaveForm(); + WF.WaveFormLoadFromMemory( waveformSave ); + WF.DrawMarker = WaveForm.MARKERDRAWTYPE.Line | WaveForm.MARKERDRAWTYPE.Name | WaveForm.MARKERDRAWTYPE.NamePositionAlternate; + this.pictureBox1.BackgroundImage = WF.CreateBitmap( this.pictureBox1.Width, this.pictureBox1.Height, -1, -1, true); + + + + + + Loads a rendered WaveForm from a byte array. + + The byte array to load the rendered data from (e.g. created with ). + If the WaveForm will be loaded from a binary format - else standard deserialization will be carried out. + on success, else . + The binary format is much more compact and faster, so it is advised to use this format. + Note, that you must load the WaveForm in the same format as it was saved. + + + private byte[] waveformSave; + ... + // save the wave form to a byte array + waveformSave = WF.WaveFormSaveToMemory(); + .. + // load the wave form to a byte array + WF = new Un4seen.Bass.Misc.WaveForm(); + WF.WaveFormLoadFromMemory( waveformSave ); + WF.DrawMarker = WaveForm.MARKERDRAWTYPE.Line | WaveForm.MARKERDRAWTYPE.Name | WaveForm.MARKERDRAWTYPE.NamePositionAlternate; + this.pictureBox1.BackgroundImage = WF.CreateBitmap( this.pictureBox1.Width, this.pictureBox1.Height, -1, -1, true); + + + + + + Gets or Sets the file name to render. Needs to be set before calling the RenderFile method. + + + + + Gets or Sets the rendering resolution in seconds. The resolution defines the length of one frame which is the smallest unit to display. + The minimum is 0.001 (1ms) and the maximum is 5.0 (5000ms, 5sec.). + Default is 0.01 = 10ms. + + + + + Gets or Sets the frequency in frames - how often the callback should be invoked (default=250, every 5sec. - if the FrameResolution is set to 20ms). + Specify 0, if you want to invoke the callback only at the end of the rendering process. + Example: Specify 50, if you want the callback to be called for every second of the deconding stream (slow - if the FrameResolution is set to 20ms). + Or specify 500 to invoke the callback for every 10 seconds (if the FrameResolution is set to 20ms) rendered. + Default is 250 = every 5sec. (if the FrameResolution is set to 20ms default). + + + + + Gets or Sets the callback delegete which should be invoked during the rendering progress started with . + + + + + Gets or Sets the application window control (use null for console applications). + This window control will be used to invoke the (if set), so that the callback will be executed in the 'correct' GUI thread, if the background option was set during . + + + + + Gets, if the wave form has already been rendered. + + + + + Gets, if the wave form rendering process is still in progress. + + + + + Gets how many frames have to be rendered in total (one frame = ms). + + + + + Gets how many frames have been rendered (one frame = ms). + When rendering has finished this should be equal to . + + + + + Gets or Sets, if the beat positions should also be detected during the rendering process. + + Note: If enabled BASS_FX is required! + + + + + Gets or Sets the tempo adjustment factor in percent (e.g. 0.05 for +5% or -0.1 for -10%, default is 0). + + Make sure to set this property after you have called (when this is needed), since will reset the tempo factor to 0. + Adjusting the tempo factor might be desired, if you want to display a zoomed wave form according to the current playback speed/tempo, if that was changes e.g. by a BASS_FX tempo stream. + Normally this is only needed, if you display two or more partial (zoomed) wave forms in parallel. + + + + + Gets the current sync factor between rendering and playback. + + The factor will reflect the difference between the resolution used during rendering and playback (e.g. because different stream flags have been used during rendering and during playback - for example rendering is done in 16-bit whereas the playback stream is using 32-bit float). + In addition the sync factor also reflects the (as the rendering is always done in the original speed whereas playback might be done at a different speed). + + + + Gets or Sets a gain factor which should be used when creating the WaveForm image to amplify the amplitude (default is 1.0 = no amplification). + + The gain factor amplifies the entire WaveForm amplitude. + Values below 1.0 will lower the signal amplitude in the image, values above 1.0 will raise the signal amplitude in the image. + + + + Gets or Sets the rendered wave buffer instance, ie. lets you access the peak levels scanned. + + Setting this property is not recommended, but possible e.g. if you want to create a reference copy of an already rendered WaveForm. + Note, that when assigning a from another instance a reference is create (not a full copy). + + + + Gets or Sets the background color to be used when drawing the wave form image (Default = SystemColors.Control). + + + + + Gets or Sets the base color (left channel) to be used when drawing the wave form image (Default = Color.Gainsboro). + + + + + Gets or Sets the gradient color (left channel) to be used when drawing the wave form image (Default = Color.Gainsboro). + + This property is only used if is set to . + + + + Gets or Sets the envelope color (left channel) to be used when drawing the wave form image (Default = Color.Gray). + + + + + Gets or Sets a flag if the envelope should be drawn in the wave form image (Default = ). + + + + + Gets or Sets a flag if the center line should be drawn in the wave form image (Default = ). + + + + + Gets or Sets the center line color (left channel) to be used when drawing the wave form image (Default = Color.Empty). + + When Color.Empty is selected the is used instead (which is the default). + + + + Gets or Sets the center line color (right channel) to be used when drawing the wave form image (Default = Color.Empty). + + When Color.Empty is selected the is used instead (which is the default). + + + + Gets or Sets a flag if the wave form should be drawn in gradient mode (Default = ). + + If set to the and resp. the and + + + + Gets or Sets the base color (right channel) to be used when drawing the wave form image (Default = Color.LightGray). + + + + + Gets or Sets the gradient color (right channel) to be used when drawing the wave form image (Default = Color.White). + + This property is only used if is set to . + + + + Gets or Sets the envelope color (right channel) to be used when drawing the wave form image (Default = Color.DimGray). + + + + + Gets or Sets the color to be used when drawing volume curve (Default = Color.IndianRed). + + + + + Gets or Sets the pixel format to use for drawing a bitmap (Default = Format32bppArgb). + + + + + Gets or Sets if and how a volume curve should be drawn in the WaveForm (Default = None). + + + Volume Curve Drawing Type: Defines how the volume curve should be drawn with the WaveForm: + + NoneNo volume curve will be drawn at all. + SolidA solid volume curve will be drawn over the WaveForm. + DottedA dotted volume curve will be drawn over the WaveForm. + NoPointsAdd this flag to supress drawing the volume point markers (eg. Solid | NoPoints). + + + + + + Gets or Sets if the initial level when drawing a volume curve should be silent (default is ). + + If the initial level at the beginning and end of the wave form is 0 (silent) - else it is at maximum (0dB). + + + + Gets or Sets the color to be used when drawing beat position marker (Default = Color.CornflowerBlue). + + + + + Gets or Sets if and how beat position should be drawn in the WaveForm (Default = None). + + + Beat Drawing Type: use one of the flags: + + NoneNo beat positions will be drawn at all. + TopThe beat position lines will be drawn at the top of the WaveForm. + BottomThe beat position lines will be drawn at the bottom of the WaveForm. + MiddleThe beat position lines will be drawn in the middle of the WaveForm. + TopBottomThe beat position lines will be drawn at the top and bottom of the WaveForm. + + + + + + Gets or Sets the length of the beat position line to be drawn in percentage of the total height (default is 0.05 = 5%). + + + + + Gets or Sets the width in pixel of the beat position line to be drawn (default is 1px). + + + + + Gets or Sets the color to be used when drawing a marker (Default = Color.DarkBlue). + + + + + Gets or Sets the font to be used when drawing a marker (Default = Arial, 7.5, regular). + + + + + Gets or Sets if and how markers should be drawn in the WaveForm (Default = None). + + + Marker Drawing Type: use any combination of the flags: + + NoneNo markers will be drawn at all. + LineThe markers lines will be drawn. + NameThe name of the markers will be drawn. + NamePositionAlternateWhen marker names are drawn, they are drawn in an alternate way (top, bottom, top, bottom, ...). + NamePositionTopWhen marker names are drawn, they are drawn on top of the marker lines. + NamePositionBottomWhen marker names are drawn, they are drawn on top of the marker lines. + NamePositionMiddleWhen marker names are drawn, they are drawn in the middle of the marker lines. + + + + + + Gets or Sets the length of the marker line to be drawn in percentage of the total height (default is 0.1 = 10%). + + + + + Gets or Sets how the wave form should be drawn (Default = Stereo). + + + WaveForm Drawing Type: use one of the following : + + StereoTwo independent wave forms will be drawn (upper=left channel, lower=right channel). + MonoOne combined mono wave form will be drawn. + DualMonoTwo overloaded mono wave forms (left, right) will be drawn. + HalfMonoOne combined mirrored half mono wave form will be drawn. + + + + + + Marker Drawing Type: Defines how markers should be drawn with the WaveForm - any combination of the following flags: + + NoneNo markers will be drawn at all. + LineThe markers lines will be drawn. + NameThe name of the markers will be drawn. + NamePositionAlternateWhen marker names are drawn, they are drawn in an alternate way (top, bottom, top, bottom, ...) - default. + NamePositionTopWhen marker names are drawn, they are drawn on top of the marker lines. + NamePositionBottomWhen marker names are drawn, they are drawn on top of the marker lines. + NamePositionMiddleWhen marker names are drawn, they are drawn in the middle of the marker lines. + + + Used in the property. + + + + No markers will be drawn at all. + + + + + The markers lines will be drawn. + + + + + The name of the markers will be drawn. + + + + + When marker names are drawn, they are drawn in an alternate way (top, bottom, top, bottom, ...) - default. + + + + + When marker names are drawn, they are drawn on top of the marker lines. + + + + + When marker names are drawn, they are drawn on top of the marker lines. + + + + + When marker names are drawn, they are drawn in the middle of the marker lines. + + + + + A box will be drawn around the marker name, filled with the color. + + + + + A box will be drawn around the marker name, filled with the color. + + + + + Volume Curve Drawing Type: Defines how the volume curve should be drawn with the WaveForm: + + NoneNo volume curve will be drawn at all. + SolidA solid volume curve will be drawn over the WaveForm. + DottedA dotted volume curve will be drawn over the WaveForm. + NoPointsAdd this flag to supress drawing the volume point markers (eg. Solid | NoPoints). + + + Used in the property. + + + + No volume curve will be drawn at all. + + + + + A solid volume curve will be drawn over the WaveForm. + + + + + A dotted volume curve will be drawn over the WaveForm. + + + + + The volume point markers will not be drawn. + + + + + Beat Drawing Type: Defines how beat positions should be drawn with the WaveForm: + + NoneNo beat positions will be drawn at all. + TopThe beat position lines will be drawn at the top of the WaveForm. + BottomThe beat position lines will be drawn at the bottom of the WaveForm. + MiddleThe beat position lines will be drawn in the middle of the WaveForm. + TopBottomThe beat position lines will be drawn at the top and bottom of the WaveForm. + + + Used in the property. + + + + No beat position will be drawn at all. + + + + + The beat position lines will be drawn at the top of the WaveForm. + + + + + The beat position lines will be drawn at the bottom of the WaveForm. + + + + + The beat position lines will be drawn in the middle of the WaveForm. + + + + + The beat position lines will be drawn at the top and bottom of the WaveForm. + + + + + WaveForm Drawing Type: Defines how the wave form should be drawn: + + StereoTwo independent wave forms will be drawn (upper=left channel, lower=right channel). + MonoOne combined mono wave form will be drawn. + DualMonoTwo overloaded mono wave forms (left, right both centered) will be drawn. + HalfMonoOne combined mirrored half mono wave form will be drawn (using , 0db at bottom). + HalfMonoFlippedOne combined mirrored half mono wave form will be drawn (using , 0db at top). + + + Used in the property. + + + + Two independent wave forms will be drawn (upper=left channel, lower=right channel). + + + + + One combined mono wave form will be drawn (using ). + + + + + Two overloaded mono wave forms (left, right both centered) will be drawn. + + + + + One combined mirrored half mono wave form will be drawn (using , 0db at bottom). + + + + + One combined mirrored half mono wave form will be drawn (using , 0db at top). + + + + + The internal class containing the rended wave buffer data (in frames). + + + + + Internal Constructor. + + + + + Will keep the related stream file name (if set). Only used internally for serialization. + + + + + Will keep the stream create flags (as an int), see . + + + + + Number of channels (1=mono, 2=stereo, ...). + + + + + Bytes per frame (one frame is a window with the length defined in ). + + + + + Frame resolution in milliseconds + + + + + Data buffer containing the rendered peak levels of the right and left channel (one element represents the data of one frame). + The and values represent each the absolute signed maximum value of the left resp. right channel' sample data within the rendered frame (e.g. -10000 would be kept instead of +8000). + If the channel is mono, then the left and right value of the would contain the same value. + Structure of one element: + + | 32-bit | + | left | right | + + + Each level ranges linearly from -32768 to 0 (silent) to +32767. + + + + + List of optional markers within the WaveForm (or , if no markers are defined). + Key (string) = Name of the marker, Value (long) = Position of the marker (in bytes of the rendering resolution). + + Markers might be used to highlight certain positions within a WaveForm, e.g. Cue-, Ramp-, Fade- or Mix-Points. + Use the property to define if and how markers should be drawn within the WaveForm. The property will be used as the the drawing color. + Markers can be get, set or removed by using the , , or methods. + Note: When using the method the position (in byte) will be converted to the original rendering resolution. + And when using the method the position will automatically be converted according to the stream. + However, if you try to access this member directly keep in mind, that marker positions should be according to it's original rendering resolution! + + + + + List of optional beat positions within the WaveForm (or , if no beat positions have been detected). + Each Element reflects one beat position (long value, in bytes of the original rendering resolution). + + + + + Returns the bytes per sample (16-bit samples will return 2, 32-bit samples will return 4 and 8-bit samples will return 1). + + + + + This structure represents one element of a array. + It consists of a and value (both in the range of -32768 and +32767). + + + + + The signed maximum value of the left channel of the the wave buffer data at this point. + + + + + The signed maximum value of the right channel of the the wave buffer data at this point. + + + + + Creates a new instance of the Level structure taking the given values. + + The left level value. + The right level value. + + + + The class represents a volume point to be used to draw a volume curve within the wave form. + + + + + Original position of the volume point. + + + + + 0f=silent, 1f=0dB. + + + + + Creates a new volume point instance. + + The byte position. + The volume level between 0f (silent) and 1f (max=0dB). + + + + Returns the string representation of a wave form volume point. + + The string of this instance representation. + + + + Compares the current object to another object based on it's . + + The VolumePoint object to compare to. + If the two objects are of the type VolumePoint, the method behaves exactly like long.CompareTo, and the returned values are: -1 if the position value is greater than the position value of the current object. + 0 if the two positions are identical. 1 if the position value is less than the position value of the current object. + + is not a VolumePoint. + + + + Callback which will be invoked during to give feedback about the current rendering progress. + + The number of frames already rendered. + The total number of frames to render. + The already elapsed rendering time. + , when rendering has finished - else (still rendering). + + + + Provides general visualisation methods to generate spectrum analyzers etc. + Requires: bass.dll - available @ www.un4seen.com + + + The Visuals class is an internal implementation of the BASS.NET API and does not require any additional extension or add-on to the BASS audio library, meaning only bass.dll is required. + There is the need to create an instance of the class in order to use it! + Most create spectrum methods have two overloads. One which directly creates a bitmap image (e.g. to be used with a PictureBox) and one which receives a Graphics GDI+ object (e.g. to be used when you build your own custom components). + Take a look at the Simple.cs demo code for a list of all spectrum graphs available. All methods accept a long list of parameters to even customize each spectrum graph. + + + + + Default constructor. Simply create an instance and use it. + + + + + Global FFT sample buffer + + + + + Returns the frequency in Hz represented by the given X coordinate position of a visual control. + + The X coordinate from which to get the frequency (between 0 and control.Width-1). + The current samplerate of the channel which was used to render the visual (e.g. use to retrieve the current samplerate of the respective channel). + The frequency in Hz which is represented by the X coordinate of the visual. + The X coordinate position represents the zero based pixel number of the visual control being rendered. + + In the following example a pictureBox control is assumed being used: + + private void pictureBoxSpectrum_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) + { + if (_vis == null) + return; + int freq = _vis.GetFrequencyFromPosX(e.X, 44100); + float amp = _vis.GetAmplitudeFromPosY(e.Y, this.pictureBoxSpectrum.Height); + this.labelVis.Text = String.Format( "Freq={0}Hz, Amp={1}", freq, amp ); + } + + + Private Sub pictureBoxSpectrum_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs) + If _vis Is Nothing Then + Return + End If + Dim freq As Integer = _vis.GetFrequencyFromPosX(e.X, 44100) + Dim amp As Single = _vis.GetAmplitudeFromPosY(e.Y, Me.pictureBoxSpectrum.Height) + Me.labelVis.Text = [String].Format("Freq={0}Hz, Amp={1}", freq, amp) + End Sub + + + + + + Returns the amplitude (power) as a float value which is represented by the given Y coordinate position of a visual control. + + The Y coordinate from which to get the amplitude (between 0 and control.Height-1). + The maximum height of the visual control which was used to display the visual (e.g. pictureBox.Height). + The amplitude or power as a float value (between 0.0 and 1.0) which is represented by the Y coordinate of the visual. + The Y coordinate position represents the zero based pixel number of the visual control being rendered. + + In the following example a pictureBox control is assumed being used: + + private void pictureBoxSpectrum_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) + { + if (_vis == null) + return; + int freq = _vis.GetFrequencyFromPosX(e.X, 44100); + float amp = _vis.GetAmplitudeFromPosY(e.Y, this.pictureBoxSpectrum.Height); + this.labelVis.Text = String.Format( "Freq={0}Hz, Amp={1}", freq, amp ); + } + + + Private Sub pictureBoxSpectrum_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs) + If _vis Is Nothing Then + Return + End If + Dim freq As Integer = _vis.GetFrequencyFromPosX(e.X, 44100) + Dim amp As Single = _vis.GetAmplitudeFromPosY(e.Y, Me.pictureBoxSpectrum.Height) + Me.labelVis.Text = [String].Format("Freq={0}Hz, Amp={1}", freq, amp) + End Sub + + + + + + Creates a bitmap representing a FFT spectrum graph. + + The channel for which to create the spectrum graph. + The width (in pixel) of the image to create. + The height (in pixel) of the image to create. + The base color (normal) for the FFT data. + The peak color for the FFT data. + The background color to be used when drawing the image. + , if linear scaling (see ) should be applied to the FFT data. , to scale by Sqr (see ) to make low values more visible (recommended). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if anti alias should be used when drawing. will draw in high speed mode. + The created bitmap image representing the spectrum. + + Using the following code in a timer routine (e.g. updated every 50ms): + + this.pictureBoxSpectrum.Image = Un4seen.Bass.Misc.Visuals.CreateSpectrum(_stream, + this.pictureBoxSpectrum.Width, + this.pictureBoxSpectrum.Height, + Color.Lime, Color.Red, Color.Black, + false, false, false); + + + Me.pictureBoxSpectrum.Image = Un4seen.Bass.Misc.Visuals.CreateSpectrum(_stream, + Me.pictureBoxSpectrum.Width, + Me.pictureBoxSpectrum.Height, + Color.Lime, Color.Red, Color.Black, + False, False, False) + + + + + + Draws the spectrum graph directly on the provided GDI+ graphics. + + The channel for which to create the spectrum graph. + The GDI+ graphics object where to draw the wave form (ie. can be taken directly from a ). + The rectangle describing the size of the wave form to draw (ie. can be taken directly from a ). + The base color (normal) for the FFT data. + The peak color for the FFT data. + The background color to be used when drawing the image. + , if linear scaling (see ) should be applied to the FFT data. , to scale by Sqr (see ) to make low values more visible (recommended). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if anti alias should be used when drawing. will draw in high speed mode. + , if successfully painted, else . + This overload is most useful when you are developing your own custom control. You might use it directly within your paint overload implementation. + + + + Creates a bitmap representing a FFT spectrum line graph. + + The channel for which to create the spectrum graph. + The width (in pixel) of the image to create. + The height (in pixel) of the image to create. + The base color (normal) for the FFT data. + The peak color for the FFT data. + The background color to be used when drawing the image. + The thickness of the line (in pixel). + The distance between the lines (in pixel). + , if linear scaling (see ) should be applied to the FFT data. , to scale by Sqr (see ) to make low values more visible (recommended). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if anti alias should be used when drawing. will draw in high speed mode. + The created bitmap image representing the spectrum. + + + + Draws the spectrum line graph directly on the provided GDI+ graphics. + + The channel for which to create the spectrum graph. + The GDI+ graphics object where to draw the wave form (ie. can be taken directly from a ). + The rectangle describing the size of the wave form to draw (ie. can be taken directly from a ). + The base color (normal) for the FFT data. + The peak color for the FFT data. + The background color to be used when drawing the image. + The thickness of the line (in pixel). + The distance between the lines (in pixel). + , if linear scaling (see ) should be applied to the FFT data. , to scale by Sqr (see ) to make low values more visible (recommended). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if anti alias should be used when drawing. will draw in high speed mode. + , if successfully painted, else . + This overload is most useful when you are developing your own custom control. You might use it directly within your paint overload implementation. + + + + Creates a bitmap representing a FFT spectrum ellipse graph. + + The channel for which to create the spectrum graph. + The width (in pixel) of the image to create. + The height (in pixel) of the image to create. + The base color (normal) for the FFT data. + The peak color for the FFT data. + The background color to be used when drawing the image. + The thickness of the line (in pixel). + The distance between the ellipses (in pixel). + , if linear scaling (see ) should be applied to the FFT data. , to scale by Sqr (see ) to make low values more visible (recommended). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if anti alias should be used when drawing. will draw in high speed mode. + The created bitmap image representing the spectrum. + + + + Draws the spectrum ellipse graph directly on the provided GDI+ graphics. + + The channel for which to create the spectrum graph. + The GDI+ graphics object where to draw the wave form (ie. can be taken directly from a ). + The rectangle describing the size of the wave form to draw (ie. can be taken directly from a ). + The base color (normal) for the FFT data. + The peak color for the FFT data. + The background color to be used when drawing the image. + The thickness of the line (in pixel). + The distance between the ellipses (in pixel). + , if linear scaling (see ) should be applied to the FFT data. , to scale by Sqr (see ) to make low values more visible (recommended). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if anti alias should be used when drawing. will draw in high speed mode. + , if successfully painted, else . + This overload is most useful when you are developing your own custom control. You might use it directly within your paint overload implementation. + + + + Creates a bitmap representing a FFT spectrum dot graph. + + The channel for which to create the spectrum graph. + The width (in pixel) of the image to create. + The height (in pixel) of the image to create. + The base color (normal) for the FFT data. + The peak color for the FFT data. + The background color to be used when drawing the image. + The thickness of the dot (in pixel). + The distance between the dots (in pixel). + , if linear scaling (see ) should be applied to the FFT data. , to scale by Sqr (see ) to make low values more visible (recommended). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if anti alias should be used when drawing. will draw in high speed mode. + The created bitmap image representing the spectrum. + + + + Draws the spectrum line graph directly on the provided GDI+ graphics. + + The channel for which to create the spectrum graph. + The GDI+ graphics object where to draw the wave form (ie. can be taken directly from a ). + The rectangle describing the size of the wave form to draw (ie. can be taken directly from a ). + The base color (normal) for the FFT data. + The peak color for the FFT data. + The background color to be used when drawing the image. + The thickness of the dot (in pixel). + The distance between the dots (in pixel). + , if linear scaling (see ) should be applied to the FFT data. , to scale by Sqr (see ) to make low values more visible (recommended). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if anti alias should be used when drawing. will draw in high speed mode. + , if successfully painted, else . + This overload is most useful when you are developing your own custom control. You might use it directly within your paint overload implementation. + + + + Creates a bitmap representing a FFT spectrum line graph with peak hold. + + The channel for which to create the spectrum graph. + The width (in pixel) of the image to create. + The height (in pixel) of the image to create. + The base color (normal) for the FFT data. + The peak color for the FFT data. + The peak hold color for the FFT data. + The background color to be used when drawing the image. + The thickness of the line (in pixel). + The thickness of the peak line (in pixel). + The distance between the lines (in pixel). + The delay how fast the peaks should fall (0=no delay, the higher the value, the slower the peaks will fall). + , if linear scaling (see ) should be applied to the FFT data. , to scale by Sqr (see ) to make low values more visible (recommended). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if anti alias should be used when drawing. will draw in high speed mode. + The created bitmap image representing the spectrum. + + + + Draws the spectrum line graph with peak hold directly on the provided GDI+ graphics. + + The channel for which to create the spectrum graph. + The GDI+ graphics object where to draw the wave form (ie. can be taken directly from a ). + The rectangle describing the size of the wave form to draw (ie. can be taken directly from a ). + The base color (normal) for the FFT data. + The peak color for the FFT data. + The peak hold color for the FFT data. + The background color to be used when drawing the image. + The thickness of the line (in pixel). + The thickness of the peak line (in pixel). + The distance between the lines (in pixel). + The delay how fast the peaks should fall (0=no delay, the higher the value, the slower the peaks will fall). + , if linear scaling (see ) should be applied to the FFT data. , to scale by Sqr (see ) to make low values more visible (recommended). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if anti alias should be used when drawing. will draw in high speed mode. + , if successfully painted, else . + This overload is most useful when you are developing your own custom control. You might use it directly within your paint overload implementation. + + + + Clears all last peak values. This is needed, if you changed from one peak spectrum to another or if you change a channel, to make sure no old history data is present. + + + + + Creates a bitmap representing a FFT spectrum wave graph. + + The channel for which to create the spectrum graph. + The width (in pixel) of the image to create. + The height (in pixel) of the image to create. + The base color (normal) for the FFT data. + The peak color for the FFT data. + The background color to be used when drawing the image. + The thickness of the line (in pixel). + , if linear scaling (see ) should be applied to the FFT data. , to scale by Sqr (see ) to make low values more visible (recommended). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if anti alias should be used when drawing. will draw in high speed mode. + The created bitmap image representing the spectrum. + + + + Draws the spectrum wave graph directly on the provided GDI+ graphics. + + The channel for which to create the spectrum graph. + The GDI+ graphics object where to draw the wave form (ie. can be taken directly from a ). + The rectangle describing the size of the wave form to draw (ie. can be taken directly from a ). + The base color (normal) for the FFT data. + The peak color for the FFT data. + The background color to be used when drawing the image. + The thickness of the line (in pixel). + , if linear scaling (see ) should be applied to the FFT data. , to scale by Sqr (see ) to make low values more visible (recommended). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if anti alias should be used when drawing. will draw in high speed mode. + , if successfully painted, else . + This overload is most useful when you are developing your own custom control. You might use it directly within your paint overload implementation. + + + + Creates a bitmap representing a sample data wave form graph. + + The channel for which to create the spectrum graph. + The width (in pixel) of the image to create. + The height (in pixel) of the image to create. + The left signal color for the sample data. + The right signal color for the sample data. + The median color (null line). + The background color to be used when drawing the image. + The thickness of the line (in pixel). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if a mono signal show be used (else a stereo signal is being used). + , if anti alias should be used when drawing. will draw in high speed mode. + The created bitmap image representing the spectrum. + + + + Draws the sample data wave form graph directly on the provided GDI+ graphics. + + The channel for which to create the spectrum graph. + The GDI+ graphics object where to draw the wave form (ie. can be taken directly from a ). + The rectangle describing the size of the wave form to draw (ie. can be taken directly from a ). + The left signal color for the sample data. + The right signal color for the sample data. + The median color (null line). + The background color to be used when drawing the image. + The thickness of the line (in pixel). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if a mono signal show be used (else a stereo signal is being used). + , if anti alias should be used when drawing. will draw in high speed mode. + , if successfully painted, else . + This overload is most useful when you are developing your own custom control. You might use it directly within your paint overload implementation. + + + + Creates a bitmap representing a FFT spectrum dancing beans graph. + + The channel for which to create the spectrum graph. + The width (in pixel) of the image to create. + The height (in pixel) of the image to create. + The base color (normal) for the FFT data. + The peak color for the FFT data. + The background color to be used when drawing the image. + The thickness of the beans (in pixel). + , if linear scaling (see ) should be applied to the FFT data. , to scale by Sqr (see ) to make low values more visible (recommended). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if anti alias should be used when drawing. will draw in high speed mode. + The created bitmap image representing the spectrum. + + + + Draws the spectrum dancing beans graph directly on the provided GDI+ graphics. + + The channel for which to create the spectrum graph. + The GDI+ graphics object where to draw the wave form (ie. can be taken directly from a ). + The rectangle describing the size of the wave form to draw (ie. can be taken directly from a ). + The base color (normal) for the FFT data. + The peak color for the FFT data. + The background color to be used when drawing the image. + The thickness of the beans (in pixel). + , if linear scaling (see ) should be applied to the FFT data. , to scale by Sqr (see ) to make low values more visible (recommended). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if anti alias should be used when drawing. will draw in high speed mode. + , if successfully painted, else . + This overload is most useful when you are developing your own custom control. You might use it directly within your paint overload implementation. + + + + Creates a bitmap representing a FFT spectrum dancing text graph. + + The channel for which to create the spectrum graph. + The width (in pixel) of the image to create. + The height (in pixel) of the image to create. + The base color (normal) for the FFT data. + The peak color for the FFT data. + The background color to be used when drawing the image. + The text characters to draw. + , if linear scaling (see ) should be applied to the FFT data. , to scale by Sqr (see ) to make low values more visible (recommended). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if anti alias should be used when drawing. will draw in high speed mode. + The created bitmap image representing the spectrum. + + + + Draws the spectrum dancing text graph directly on the provided GDI+ graphics. + + The channel for which to create the spectrum graph. + The GDI+ graphics object where to draw the wave form (ie. can be taken directly from a ). + The rectangle describing the size of the wave form to draw (ie. can be taken directly from a ). + The base color (normal) for the FFT data. + The peak color for the FFT data. + The background color to be used when drawing the image. + The text characters to draw. + , if linear scaling (see ) should be applied to the FFT data. , to scale by Sqr (see ) to make low values more visible (recommended). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if anti alias should be used when drawing. will draw in high speed mode. + , if successfully painted, else . + This overload is most useful when you are developing your own custom control. You might use it directly within your paint overload implementation. + + + + Gets the interpolated amplification value for a given frequency band. + + The channel for which to detect the presence of the frequency band. + The lower bound of the frequency band (in Hz). + The upper bound of the frequency band (in Hz). + , if linear scaling (see ) should be applied to the FFT data. , to scale by Sqr (see ) to make low values more visible (recommended). + The interpolated amplification level of the given frequency band. Note: The level is scaled either linerar or by Sqr, meaning values above 1.0 can be returned. + + + + + Returns the frequency (in Hz) containing the maximum energy within the current FFT data when calling this method. + + The channel for which to detect the peak frequency. + Returns the energy (amplitude level) of the detected peak frequency. + The frequency (in Hz) containing the most energy. Or 0, if an error occurred. + + + + Draws one line of a 3D voice print spectrum at the given position. + horizontal=time, vertical=frequency, color=amplitude + + The channel for which to create the spectrum graph. + The GDI+ graphics object where to draw the wave form (ie. can be taken directly from a or can be created using ). + The rectangle describing the size of the wave form to draw (ie. can be taken directly from a ). + The base color of the 3D voice print (only the RED component is taken). + The color of the position marker. + The position where to plot the 3D line + , if linear scaling (see ) should be applied to the FFT data. , to scale by Sqr (see ) to make low values more visible (recommended). + , if the full frequency spectrum should be shown (across the whole width of the image). + , if the width of the image should be use (in this case as much frequencies are shown - starting with the lower values - as fit into the width). + , if successfully painted, else . + You need to call this method frequently and increase the position by 1 every time in order to plot the voice print over time. + The amplitude color (GREEN and BLUE component) is calculated from the FFT sample data (RED component is taken from the color1 parameter). + + + + + Gets or Sets, if the channel being used in one of the Create methods (e.g. ) is a buffered mixer source channel. (Default=). + + When setting this property to , the BASS_MIXER_BUFFER flag must have been used on the channel. + And such instead of call BASS_ChannelGetData, BASS_Mixer_ChannelGetData will be called internaly to query the FFT data. + + + + Gets or Sets the scaling factor to apply when linear spectrum drawing is selected. (Default=9). + + + + + Gets or Sets the scaling factor to apply when non-linear spectrum drawing is selected to make low values more visible. (Default=4). + + + + + Gets the number of FFT data used (see (Defaut is 4096). + + + + + Gets the maximum FFT data index which can be used (according to , default is 2047). + + + + + Gets or Sets the number of FFT data to get (can be either , , , or (Default is 4096). + + The higher the resolution, the more sample data is needed and the more complex the FFT calculation is. + + + + Gets or Sets the maximum number of samples to use when the fullSpectrum option is used (Default=2047 - all). + By default the full spectrum is drawn, which are 2047 samples. With this option you might limit this, since very high frequencies are often not much relevant for a visual display. + You might use the method with a length value of here to calculate an index for a desired upper limit frequency. + E.g. if you want to limit the full spectrum display to an upper limit of around 11843Hz with a stream having a sampling rate of 44100Hz you might set this value to 1100. + + + + + BASS.NET API wrapper for BASSWMA.DLL + Requires: basswma.dll - Windows Media Audio Format (WMA) Add-On - available @ www.un4seen.com. + The Windows Media Format modules are also required to be installed on the user's system. They are installed with Windows Media Player, so will already be on most users' systems, but they can also be installed separately (WMFDIST.EXE). + + + BASSWMA is an extension to the BASS audio library, enabling the playback of WMA files and network streams. The audio tracks of WMV files can also be played. WMA file encoding and network broadcasting functions are also provided. + The WMA format is used in very much the same way as any of the built-in BASS stream formats - simply call the WMA stream creation function instead of the BASS built-in functions. The BASS plugin system (see ) is also supported for local WMA files. + More information can be found on Microsoft Windows Media — Your Digital Entertainment Resource. + + + + + NOT used - all members are static! + + + + + + + + + + + + + + + + Creates a sample stream from an IStream object. + + A pointer to an IStream object. + Unused... set to 0. + Unused... set to 0. + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + Use to retrieve information on the format (sample rate, resolution, channels) of the stream. The bitrate (amongst other things) can be retrieved through (BASS_TAG_WMA). When retrieving tags, a pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. + A description of the codec used by the file is also available from (BASS_TAG_WMA_CODEC). 2 null-terminated UTF-8 strings are returned, with the 1st string being the name of the codec, and the 2nd containing additional information like what VBR setting was used. + The playback length of the stream can be retrieved using . Until the whole file has been streamed, whatever length the file's header says is returned, which may or may not be exact. + Although the Windows Media modules uses it's own internet streaming code (not BASS's), the BASS_CONFIG_NET_TIMEOUT (see ) config option does have effect when opening WMA streams. None of the other NET config options apply. + With local files, works the same as with the BASS built-in stream formats. But when internet streaming, the Windows Media modules uses it's own streaming routines. + The download progress of an internet streamed file can be retrieved with (BASS_FILEPOS_DOWNLOAD). The file size (BASS_FILEPOS_END) can also be retrieved, but getting the size of internet streamed files requires Windows Media 9 to be installed. + The decode position (BASS_FILEPOS_CURRENT) is not available. When streaming a file from the internet, it is not possible to seek with until the whole file has been downloaded. A sync ( with BASS_SYNC_DOWNLOAD) can be set to be notified when the file has been downloaded. + When streaming a file from the internet, it's not possible to seek with until the whole file has been downloaded. A sync (BASS_SYNC_DOWNLOAD) can be set to be notified when the file has been downloaded. + With Windows Media versions prior to 9 (and when streaming from the internet), WMA decoding is performed in a separate thread, so the CPU used to decode a file/stream during playback will not be included in the return value. + When using the BASS_STREAM_DECODE flag, it's not possible to play the stream. Because the decoded sample data is not outputted, "decoding channels" can still be used when there is no output device (using the "no sound" device with ). + The sample rate of local files can be altered with . But the playback rate of internet streams should not be changed, because they are decoded at a fixed rate - the rate required to sustain playback at normal speed. So increasing the rate will result in playback stalling. + Using VBR, lossless and multi-channel WMA files/streams requires Windows Media 9 to be installed. + + + ERROR CODEDescription + BASS_ERROR_WMAThe Windows Media modules (v9 or above) are not installed. + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_ILLPARAMOne or more of the parameters are invalid. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_CODECThere is no appropriate codec installed to decode the file. Try installing the latest Windows Media codecs. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_WMA_LICENSEThe WMA file can not be played because it is protected. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + + + + + + + + + + + + Creates a sample stream from a WMA file. + This overload implements unicode filenames. The BASS_UNICODE flag will be added automatically. + + Filename or URL for which a stream should be created. + File offset to begin streaming from (Unused, set to 0). + Data length... 0 = use all data up to the end of the file. + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + Use to retrieve information on the format (sample rate, resolution, channels) of the stream. The bitrate (amongst other things) can be retrieved through (BASS_TAG_WMA). When retrieving tags, a pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. + A description of the codec used by the file is also available from (BASS_TAG_WMA_CODEC). 2 null-terminated UTF-8 strings are returned, with the 1st string being the name of the codec, and the 2nd containing additional information like what VBR setting was used. + The playback length of the stream can be retrieved using . Until the whole file has been streamed, whatever length the file's header says is returned, which may or may not be exact. + Unless the BASS_CONFIG_WMA_BASSFILE config option is enabled, the Windows Media modules uses its own file reading routines, and the and parameters are ignored, except that length is still the length when playing from memory. + Also, isn't fully supported. The file size (BASS_FILEPOS_END) can be retrieved, but the decode position (BASS_FILEPOS_CURRENT) is not available. + The download progress of streamed files (BASS_FILEPOS_DOWNLOAD) can also be retrieved. The buffering progress (percentage) can be retrieved using the BASS_FILEPOS_WMA_BUFFER mode. + When streaming a file from the internet, it's not possible to seek with until the whole file has been downloaded. A sync (BASS_SYNC_DOWNLOAD) can be set to be notified when the file has been downloaded. + With Windows Media versions prior to 9 (and when streaming from the internet), WMA decoding is performed in a separate thread, so the CPU used to decode a file/stream during playback will not be included in the return value. + When using the BASS_STREAM_DECODE flag, it's not possible to play the stream. Because the decoded sample data is not outputted, "decoding channels" can still be used when there is no output device (using the "no sound" device with ). + The sample rate of local files can be altered with . But the playback rate of internet streams should not be changed, because they are decoded at a fixed rate - the rate required to sustain playback at normal speed. So increasing the rate will result in playback stalling. + Using VBR, lossless and multi-channel WMA files/streams requires Windows Media 9 to be installed. + + + ERROR CODEDescription + BASS_ERROR_WMAThe Windows Media modules (v9 or above) are not installed. + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_ILLPARAMOne or more of the parameters are invalid. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_CODECThere is no appropriate codec installed to decode the file. Try installing the latest Windows Media codecs. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_WMA_LICENSEThe WMA file can not be played because it is protected. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + See . + + + + + + + + + + + + + + + Creates a sample stream from a WMA memory IntPtr. + This overload implements streaming from memory. + + An unmanaged pointer to the memory location as an IntPtr. + Offset to begin streaming from (unused for memory streams, set to 0). + Data length (needs to be set to the length of the memory streams in bytes which should be played). + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + Use to retrieve information on the format (sample rate, resolution, channels) of the stream. The bitrate (amongst other things) can be retrieved through (BASS_TAG_WMA). When retrieving tags, a pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. + A description of the codec used by the file is also available from (BASS_TAG_WMA_CODEC). 2 null-terminated UTF-8 strings are returned, with the 1st string being the name of the codec, and the 2nd containing additional information like what VBR setting was used. + The playback length of the stream can be retrieved using . Until the whole file has been streamed, whatever length the file's header says is returned, which may or may not be exact. + Although the Windows Media modules uses it's own internet streaming code (not BASS's), the BASS_CONFIG_NET_TIMEOUT (see ) config option does have effect when opening WMA streams. None of the other NET config options apply. + With local files, works the same as with the BASS built-in stream formats. But when internet streaming, the Windows Media modules uses it's own streaming routines. + The download progress of an internet streamed file can be retrieved with (BASS_FILEPOS_DOWNLOAD). The file size (BASS_FILEPOS_END) can also be retrieved, but getting the size of internet streamed files requires Windows Media 9 to be installed. + The decode position (BASS_FILEPOS_CURRENT) is not available. When streaming a file from the internet, it is not possible to seek with until the whole file has been downloaded. A sync ( with BASS_SYNC_DOWNLOAD) can be set to be notified when the file has been downloaded. + When streaming a file from the internet, it's not possible to seek with until the whole file has been downloaded. A sync (BASS_SYNC_DOWNLOAD) can be set to be notified when the file has been downloaded. + With Windows Media versions prior to 9 (and when streaming from the internet), WMA decoding is performed in a separate thread, so the CPU used to decode a file/stream during playback will not be included in the return value. + When using the BASS_STREAM_DECODE flag, it's not possible to play the stream. Because the decoded sample data is not outputted, "decoding channels" can still be used when there is no output device (using the "no sound" device with ). + The sample rate of local files can be altered with . But the playback rate of internet streams should not be changed, because they are decoded at a fixed rate - the rate required to sustain playback at normal speed. So increasing the rate will result in playback stalling. + Using VBR, lossless and multi-channel WMA files/streams requires Windows Media 9 to be installed. + Don't forget to pin your memory object when using this overload. + + + ERROR CODEDescription + BASS_ERROR_WMAThe Windows Media modules (v9 or above) are not installed. + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_ILLPARAMOne or more of the parameters are invalid. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_CODECThere is no appropriate codec installed to decode the file. Try installing the latest Windows Media codecs. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_WMA_LICENSEThe WMA file can not be played because it is protected. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + See . + + + + + + + + + + + + + + + + + Creates a sample stream from an IStream object. + This overload implements UNICODE user name and password. The BASS_UNICODE flag will be added automatically, if not alreday set. + + A pointer to an IStream object. + Unused... set to 0. + Unused... set to 0. + Any combination of these flags: see . + Username to use in connecting to the server... if either this or pass is , then no username/password is sent to the server. + Password to use in connecting to the server + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + This function is identical to , but with the additional authentication options. + Use to retrieve information on the format (sample rate, resolution, channels) of the stream. The bitrate (amongst other things) can be retrieved through (BASS_TAG_WMA). When retrieving tags, a pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. + A description of the codec used by the file is also available from (BASS_TAG_WMA_CODEC). 2 null-terminated UTF-8 strings are returned, with the 1st string being the name of the codec, and the 2nd containing additional information like what VBR setting was used. + The playback length of the stream can be retrieved using . Until the whole file has been streamed, whatever length the file's header says is returned, which may or may not be exact. + Although the Windows Media modules uses it's own internet streaming code (not BASS's), the BASS_CONFIG_NET_TIMEOUT (see ) config option does have effect when opening WMA streams. None of the other NET config options apply. + With local files, works the same as with the BASS built-in stream formats. But when internet streaming, the Windows Media modules uses it's own streaming routines. + The download progress of an internet streamed file can be retrieved with (BASS_FILEPOS_DOWNLOAD). The file size (BASS_FILEPOS_END) can also be retrieved, but getting the size of internet streamed files requires Windows Media 9 to be installed. + The decode position (BASS_FILEPOS_CURRENT) is not available. When streaming a file from the internet, it is not possible to seek with until the whole file has been downloaded. A sync ( with BASS_SYNC_DOWNLOAD) can be set to be notified when the file has been downloaded. + When streaming a file from the internet, it's not possible to seek with until the whole file has been downloaded. A sync (BASS_SYNC_DOWNLOAD) can be set to be notified when the file has been downloaded. + With Windows Media versions prior to 9 (and when streaming from the internet), WMA decoding is performed in a separate thread, so the CPU used to decode a file/stream during playback will not be included in the return value. + When using the BASS_STREAM_DECODE flag, it's not possible to play the stream. Because the decoded sample data is not outputted, "decoding channels" can still be used when there is no output device (using the "no sound" device with ). + The sample rate of local files can be altered with . But the playback rate of internet streams should not be changed, because they are decoded at a fixed rate - the rate required to sustain playback at normal speed. So increasing the rate will result in playback stalling. + Using VBR, lossless and multi-channel WMA files/streams requires Windows Media 9 to be installed. + + + ERROR CODEDescription + BASS_ERROR_WMAThe Windows Media modules (v9 or above) are not installed. + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_ILLPARAMOne or more of the parameters are invalid. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_CODECThere is no appropriate codec installed to decode the file. Try installing the latest Windows Media codecs. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_WMA_LICENSEThe WMA file can not be played because it is protected. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + + + + + + + + + + + + + + Creates a sample stream from a WMA file. + This overload implements Unicode filenames, username and password. The BASS_UNICODE flag will be added automatically. + + Filename or URL for which a stream should be created. + File offset to begin streaming from (Unused, set to 0). + Data length... 0 = use all data up to the end of the file. + Any combination of these flags: see . + Username to use in connecting to the server... if either this or pass is , then no username/password is sent to the server. + Password to use in connecting to the server + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + This function is identical to , but with the additional authentication options. + Use to retrieve information on the format (sample rate, resolution, channels) of the stream. The bitrate (amongst other things) can be retrieved through (BASS_TAG_WMA). When retrieving tags, a pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. + A description of the codec used by the file is also available from (BASS_TAG_WMA_CODEC). 2 null-terminated UTF-8 strings are returned, with the 1st string being the name of the codec, and the 2nd containing additional information like what VBR setting was used. + The playback length of the stream can be retrieved using . Until the whole file has been streamed, whatever length the file's header says is returned, which may or may not be exact. + Although the Windows Media modules uses it's own internet streaming code (not BASS's), the BASS_CONFIG_NET_TIMEOUT (see ) config option does have effect when opening WMA streams. None of the other NET config options apply. + With local files, works the same as with the BASS built-in stream formats. But when internet streaming, the Windows Media modules uses it's own streaming routines. + The download progress of an internet streamed file can be retrieved with (BASS_FILEPOS_DOWNLOAD). The file size (BASS_FILEPOS_END) can also be retrieved, but getting the size of internet streamed files requires Windows Media 9 to be installed. + The decode position (BASS_FILEPOS_CURRENT) is not available. When streaming a file from the internet, it is not possible to seek with until the whole file has been downloaded. A sync ( with BASS_SYNC_DOWNLOAD) can be set to be notified when the file has been downloaded. + When streaming a file from the internet, it's not possible to seek with until the whole file has been downloaded. A sync (BASS_SYNC_DOWNLOAD) can be set to be notified when the file has been downloaded. + With Windows Media versions prior to 9 (and when streaming from the internet), WMA decoding is performed in a separate thread, so the CPU used to decode a file/stream during playback will not be included in the return value. + When using the BASS_STREAM_DECODE flag, it's not possible to play the stream. Because the decoded sample data is not outputted, "decoding channels" can still be used when there is no output device (using the "no sound" device with ). + The sample rate of local files can be altered with . But the playback rate of internet streams should not be changed, because they are decoded at a fixed rate - the rate required to sustain playback at normal speed. So increasing the rate will result in playback stalling. + Using VBR, lossless and multi-channel WMA files/streams requires Windows Media 9 to be installed. + + + ERROR CODEDescription + BASS_ERROR_WMAThe Windows Media modules (v9 or above) are not installed. + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_ILLPARAMOne or more of the parameters are invalid. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_CODECThere is no appropriate codec installed to decode the file. Try installing the latest Windows Media codecs. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_WMA_LICENSEThe WMA file can not be played because it is protected. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + + + + + + + + + + + + + + Creates a sample stream from a WMA memory IntPtr. + This overload implements streaming from memory. Username and Password are UNICODE, so the BASS_UNICODE flag will be added automatically. + + An unmanaged pointer to the memory location as an IntPtr. + Offset to begin streaming from (unused for memory streams, set to 0). + Data length (needs to be set to the length of the memory streams in bytes which should be played). + Any combination of these flags: see . + Username to use in connecting to the server... if either this or pass is , then no username/password is sent to the server. + Password to use in connecting to the server + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + This function is identical to , but with the additional authentication options. + Use to retrieve information on the format (sample rate, resolution, channels) of the stream. The bitrate (amongst other things) can be retrieved through (BASS_TAG_WMA). When retrieving tags, a pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. + A description of the codec used by the file is also available from (BASS_TAG_WMA_CODEC). 2 null-terminated UTF-8 strings are returned, with the 1st string being the name of the codec, and the 2nd containing additional information like what VBR setting was used. + The playback length of the stream can be retrieved using . Until the whole file has been streamed, whatever length the file's header says is returned, which may or may not be exact. + Although the Windows Media modules uses it's own internet streaming code (not BASS's), the BASS_CONFIG_NET_TIMEOUT (see ) config option does have effect when opening WMA streams. None of the other NET config options apply. + With local files, works the same as with the BASS built-in stream formats. But when internet streaming, the Windows Media modules uses it's own streaming routines. + The download progress of an internet streamed file can be retrieved with (BASS_FILEPOS_DOWNLOAD). The file size (BASS_FILEPOS_END) can also be retrieved, but getting the size of internet streamed files requires Windows Media 9 to be installed. + The decode position (BASS_FILEPOS_CURRENT) is not available. When streaming a file from the internet, it is not possible to seek with until the whole file has been downloaded. A sync ( with BASS_SYNC_DOWNLOAD) can be set to be notified when the file has been downloaded. + When streaming a file from the internet, it's not possible to seek with until the whole file has been downloaded. A sync (BASS_SYNC_DOWNLOAD) can be set to be notified when the file has been downloaded. + With Windows Media versions prior to 9 (and when streaming from the internet), WMA decoding is performed in a separate thread, so the CPU used to decode a file/stream during playback will not be included in the return value. + When using the BASS_STREAM_DECODE flag, it's not possible to play the stream. Because the decoded sample data is not outputted, "decoding channels" can still be used when there is no output device (using the "no sound" device with ). + The sample rate of local files can be altered with . But the playback rate of internet streams should not be changed, because they are decoded at a fixed rate - the rate required to sustain playback at normal speed. So increasing the rate will result in playback stalling. + Using VBR, lossless and multi-channel WMA files/streams requires Windows Media 9 to be installed. + Don't forget to pin your memory object when using this overload. + + + ERROR CODEDescription + BASS_ERROR_WMAThe Windows Media modules (v9 or above) are not installed. + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_ILLPARAMOne or more of the parameters are invalid. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_CODECThere is no appropriate codec installed to decode the file. Try installing the latest Windows Media codecs. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_WMA_LICENSEThe WMA file can not be played because it is protected. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Creates a sample stream from a WMA file via a user callback function. + + File system to use: see . + Any combination of these flags: see . + The user defined file functions (see ). + User instance data to pass to the callback functions. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + ERROR CODEDescription + BASS_ERROR_WMAThe Windows Media modules (v9 or above) are not installed. + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_ILLPARAMOne or more of the parameters are invalid. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_CODECThere is no appropriate codec installed to decode the file. Try installing the latest Windows Media codecs. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_WMA_LICENSEThe WMA file can not be played because it is protected. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + See . + + + + Creates a sample stream from a URL. + This overload implements Unicode urls. The BASS_UNICODE flag will be added automatically. + + URL for which a stream should be created. + Unused... set to 0. + Unused... set to 0. + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + Use to retrieve information on the format (sample rate, resolution, channels) of the stream. The bitrate (amongst other things) can be retrieved through (BASS_TAG_WMA). When retrieving tags, a pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. + A description of the codec used by the file is also available from (BASS_TAG_WMA_CODEC). 2 null-terminated UTF-8 strings are returned, with the 1st string being the name of the codec, and the 2nd containing additional information like what VBR setting was used. + The playback length of the stream can be retrieved using . Until the whole file has been streamed, whatever length the file's header says is returned, which may or may not be exact. + When loading from a memory location (mem = ), unlike , this function makes a copy of the data. So you can release the source memory immediately after calling this function. + Although the Windows Media modules uses it's own internet streaming code (not BASS's), the BASS_CONFIG_NET_TIMEOUT (see ) config option does have effect when opening WMA streams. None of the other NET config options apply. + The download progress of an internet streamed file can be retrieved with (BASS_FILEPOS_DOWNLOAD). The file size (BASS_FILEPOS_END) can also be retrieved, but getting the size of internet streamed files requires Windows Media 9 to be installed. + The decode position (BASS_FILEPOS_CURRENT) is not available. When streaming a file from the internet, it is not possible to seek with until the whole file has been downloaded. A sync ( with BASS_SYNC_DOWNLOAD) can be set to be notified when the file has been downloaded. + With Windows Media versions prior to 9 (and when streaming from the internet), WMA decoding is performed in a separate thread, so the CPU used to decode a file/stream during playback will not be included in the return value. + When using the BASS_STREAM_DECODE flag, it's not possible to play the stream. Because the decoded sample data is not outputted, "decoding channels" can still be used when there is no output device (using the "no sound" device with ). + The sample rate of local files can be altered with . But the playback rate of internet streams should not be changed, because they are decoded at a fixed rate - the rate required to sustain playback at normal speed. So increasing the rate will result in playback stalling. + Using VBR, lossless and multi-channel WMA files/streams requires Windows Media 9 to be installed. + + + ERROR CODEDescription + BASS_ERROR_WMAThe Windows Media modules (v9 or above) are not installed. + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_ILLPARAMOne or more of the parameters are invalid. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_CODECThere is no appropriate codec installed to decode the file. Try installing the latest Windows Media codecs. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_WMA_LICENSEThe WMA file can not be played because it is protected. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Retrieves a pointer to the IWMReader interface of a WMA stream, or IWMWriter interface of a WMA encoder. + + The WMA stream or encoder handle. + If succesful, then a pointer to the requested object is returned, otherwise is returned. Use to get the error code. + + This function allows those that are familiar with the Windows Media Format SDK to access the internal object interface, for extra functionality. + If you create any objects through a retrieved interface, make sure you release the objects before calling . + See the Windows Media Format SDK for information on the IWMReader and associated interfaces. + When streaming local (not internet) files, this function may actually return an IWMSyncReader interface instead of an IWMReader interface. + The type of interface can be determined by querying other interfaces from it, e.g. IWMReaderAdvanced. + See the Windows Media Format SDK for information on the IWMReader, IWMWriter and associated interfaces. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + Example using the WMFSDK function wrapper and casting it to the IWMHeaderInfo3: + + IntPtr pUnk = Un4seen.Bass.AddOn.Wma.BassWma.BASS_WMA_GetWMObject(stream); + IWMHeaderInfo3 headerInfo3 = (IWMHeaderInfo3)Marshal.GetObjectForIUnknown( pUnk ); + if (headerInfo3 != null) + { + ... + } + + + Dim pUnk As IntPtr = Un4seen.Bass.AddOn.Wma.BassWma.BASS_WMA_GetWMObject(stream) + Dim headerInfo3 As IWMHeaderInfo3 = CType(Marshal.GetObjectForIUnknown(pUnk), IWMHeaderInfo3) + If Not (headerInfo3 Is Nothing) Then + ... + End If + + + + + + + + + + + + + + Get the tags from a file, can be used on DRM protected files (not thread-safe!). + + Filename from which to get the tags. + If succesful, a pointer to the data of the requested tags is returned, else is returned. Use to get the error code. + This function gives the same tags as (BASS_TAG_WMA), which is a pointer to a series of null-terminated UTF-8 strings, the final string ending with a double null. + Unlike , this function can also be used with DRM-protected WMA files without a DRM licence, as it does not require a stream to be created. + The memory used for the tags is reused by all calls of this function, so if the tags need to be retained across multiple calls, a copy should be made. It also means that this function is not thread-safe, that is it should not be called simultaneously from multiple threads. + + + ERROR CODEDescription + BASS_ERROR_WMAThe Windows Media modules (v9 or above) are not installed. + BASS_ERROR_FILEOPENThe file could not be opened, or it is not a WMA file. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Get the tags from a file, can be used on DRM protected files (not thread-safe!). + This special helper method already evaluates the null-terminated and variable length data block using UTF-8 strings. + + Filename from which to get the tags. + or an array of strings. Each array element will represent one tag, e.g. "TITLE=this is a title" + Only available when using with a DRM protected WMA file. + + + ERROR CODEDescription + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + + + + + + + + + + + Retrieves the WMA encoding bitrates available for a specified sample format. + + The sample rate in Hz. + The number of channels (1=mono, 2=stereo, etc.). + Any combination of these flags (see ): + + BASS_WMA_ENCODE_RATES_VBRGet available VBR (Variable BitRate) quality settings. + BASS_WMA_ENCODE_RATES_CBRGet available CBR (Constant BitRate) quality settings. + BASS_WMA_ENCODE_STANDARDGet only bitrates available for standard WMA encoding. If neither this or the BASS_WMA_ENCODE_PRO flag is specified, then the bitrates available for either codec are returned. + BASS_WMA_ENCODE_PROGet only bitrates available for WMA Pro encoding. + BASS_WMA_ENCODE_24BITGet available bitrates for 24-bit encoding, else 16-bit encoding rates. + + + If succesful, an array of the available bitrates is returned (int[], in bits per second), else is returned. Use to get the error code. + + When requesting VBR rates, the rates returned are quality settings. For example, 10 = 10% quality, 25 = 25% quality, etc... 100% quality is lossless. + The WMA codec expects 16-bit or 24-bit sample data depending on the BASS_WMA_ENCODE_24BIT flag, but BASSWMA will accept 8-bit, 16-bit or floating-point data, and convert it to the appropriate format. Of course, it makes little sense to encode 8-bit or 16-bit data in 24-bit. + The WMA codec currently supports the following sample rates: 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200, 96000. And the following number of channels: 1, 2, 6, 8. But not all combinations of these are supported. To encode other sample formats, the data will first have to be resampled to a supported format. + + + ERROR CODEDescription + BASS_ERROR_WMAThe Windows Media modules (v9 or above) are not installed. + BASS_ERROR_NOTAVAILNo codec could be found to support the specified sample format. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + List the CBR bitrates available at 44100hz 16-bit stereo: + + int[] bitrates = BassWma.BASS_WMA_EncodeGetRates(44100, 2, BASSWMAEncode.BASS_WMA_ENCODE_RATES_CBR ); + if (bitrates != null) + { + foreach (int bitrate in bitrates) + Console.WriteLine( bitrate ); + } + + + Dim bitrates As Integer() = BassWma.BASS_WMA_EncodeGetRates(44100, 2, BASSWMAEncode.BASS_WMA_ENCODE_RATES_CBR) + If Not (bitrates Is Nothing) Then + Dim bitrate As Integer + For Each bitrate In bitrates + Console.WriteLine(bitrate) + Next bitrate + End If + + + + + + Initializes WMA encoding to a user defined function. + + The sample rate in Hz. + The number of channels (1=mono, 2=stereo, etc.). + Any combination of these flags (see ): + + BASS_SAMPLE_8BITS8-bit sample data. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then 16-bit data is expected. + BASS_SAMPLE_FLOAT32-bit floating-point sample data. + BASS_WMA_ENCODE_STANDARDUse standard WMA encoding. If neither this or the BASS_WMA_ENCODE_PRO flag is specified, then either codec could be used (whichever supports the requested sample format and bitrate). + BASS_WMA_ENCODE_PROUse WMA Professional encoding. + BASS_WMA_ENCODE_PCMWrite uncompressed PCM data in an ASF container. bitrate is ignored except that it should be non-0. + BASS_WMA_ENCODE_24BITEncode in 24-bit, else 16-bit. 24-bit encoding requires WMA Pro. + BASS_WMA_ENCODE_SCRIPTEnable the specification of tags mid-stream (after encoding has begun). + + + The encoding bitrate (in bits per second, e.g. 128000), or VBR quality (100 or less). + The user defined function to receive the encoded data (see ). + User instance data to pass to the callback function. + If succesful, the new encoder's handle is returned, else 0 is returned. Use to get the error code. + + Encoding to a user defined function allows any storage or delivery method to be used for the encoded WMA data. For example, encoding to memory. + The WMA codec expects 16-bit or 24-bit sample data depending on the BASS_WMA_ENCODE_24BIT flag, but BASSWMA will accept 8-bit, 16-bit or floating-point data, and convert it to the appropriate format. Use to retrieve a list of the encoding bitrates available for a specific sample format. + Use for each tag you wish to set. + Use to encode sample data, and to finish encoding. + + + ERROR CODEDescription + BASS_ERROR_WMAThe Windows Media modules (v9 or above) are not installed. + BASS_ERROR_NOTAVAILNo codec could be found to support the specified sample format and bitrate. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + // the encoding callback + private WMENCODEPROC _myEndoderProc; + private FileStream _fs; + private byte[] _encbuffer = new byte[1048510]; // 1MB buffer, should be enough + ... + // open a wma file + _fs = File.OpenRead("test.wma"); + // create the encoder (44kHz, stereo at 64kbps, no tags) + _myEndoderProc = new WMENCODEPROC(MyEncodingWriter); + int encoder = BassWma.BASS_WMA_EncodeOpen(44100, 2, BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, + 64000, _myEndoderProc, IntPtr.Zero); + ... + private bool MyEncodingWriter(int handle, BASSWMAEncodeCallback type, IntPtr buffer, int length, IntPtr user) + { + if (type == BASSWMAEncodeCallback.BASS_WMA_ENCODE_HEAD) + { + // rewind to start of file to write the header + _fs.Position = 0L; + } + + if (type == BASSWMAEncodeCallback.BASS_WMA_ENCODE_DONE) + { + // done encoding - close the file + _fs.Flush(); + _fs.Close(); + } + else + { + // copy the unmanaged buffer content to out managed buffer + Marshal.Copy(buffer, _encbuffer, 0, length); + // process the data in _encbuffer + _fs.Write(_encbuffer, 0, length); + } + } + + + Private _myEndoderProc As WMENCODEPROC + Private _fs As FileStream + Private _encbuffer(1048510) As Byte ' 1MB buffer, should be enough + ... + ' open a wma file + _fs = File.OpenRead("test.wma") + ' create the encoder (44kHz, stereo at 64kbps, no tags) + _myEndoderProc = New WMENCODEPROC(AddressOf MyEncodingWriter) + Dim encoder As Integer = BassWma.BASS_WMA_EncodeOpen(44100, 2, BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, + 64000, _myEndoderProc, IntPtr.Zero) + ... + Private Function MyEncodingWriter(handle As Integer, type As BASSWMAEncodeCallback, + buffer As IntPtr, length As Integer, user As IntPtr) As Boolean + If type = BASSWMAEncodeCallback.BASS_WMA_ENCODE_HEAD Then + ' rewind to start of file to write the header + _fs.Position = 0L.ToUInt32() + End If + + If type = BASSWMAEncodeCallback.BASS_WMA_ENCODE_DONE Then + ' done encoding - close the file + _fs.Flush() + _fs.Close() + Else + ' copy the unmanaged buffer content to out managed buffer + Marshal.Copy(buffer, _encbuffer, 0, length) + ' process the data in _encbuffer + _fs.Write(_encbuffer, 0, length) + End If + End Function + + NOTE: This is just an example. It's obviously simpler to use to encode to a file. + + + + + + + + + + + + + + + + Initializes WMA encoding to a file. + This overload implements UNICODE filenames. The BASS_UNICODE flag will be added automatically, since all .Net strings are always unicode. + + The sample rate in Hz. + The number of channels (1=mono, 2=stereo, etc.). + Any combination of these flags (see ): + + BASS_SAMPLE_8BITS8-bit sample data. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then 16-bit data is expected. + BASS_SAMPLE_FLOAT32-bit floating-point sample data. + BASS_WMA_ENCODE_STANDARDUse standard WMA encoding. If neither this or the BASS_WMA_ENCODE_PRO flag is specified, then either codec could be used (whichever supports the requested sample format and bitrate). + BASS_WMA_ENCODE_PROUse WMA Professional encoding. + BASS_WMA_ENCODE_PCMWrite uncompressed PCM data in an ASF container. bitrate is ignored except that it should be non-0. + BASS_WMA_ENCODE_24BITEncode in 24-bit, else 16-bit. 24-bit encoding requires WMA Pro. + BASS_WMA_ENCODE_SCRIPTEnable the specification of tags mid-stream (after encoding has begun). + BASS_UNICODEFile is a Unicode (16-bit characters) filename. + + + The encoding bitrate (in bits per second, e.g. 128000), or VBR quality (100 or less). + The filename to write. + If succesful, the new encoder's handle is returned, else 0 is returned. Use to get the error code. + + The WMA codec expects 16-bit or 24-bit sample data depending on the BASS_WMA_ENCODE_24BIT flag, but BASSWMA will accept 8-bit, 16-bit or floating-point data, and convert it to the appropriate format. Use to retrieve a list of the encoding bitrates available for a specific sample format. + Use for each tag you wish to set. + Use to encode sample data, and to finish encoding and close the file. + + + ERROR CODEDescription + BASS_ERROR_WMAThe Windows Media modules (v9 or above) are not installed. + BASS_ERROR_NOTAVAILNo codec could be found to support the specified sample format and bitrate. + BASS_ERROR_CREATECould not create the file to write the WMA stream. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Initialize encoding 44100hz 16-bit stereo sample data at 128kb/s to a file called "output.wma": + + int stream = Bass.BASS_StreamCreateFile("input.mp3", 0L, 0L, BASSFlag.BASS_STREAM_DECODE); + if (stream != 0) + { + byte[] buffer = new byte[16384]; // 16KB decode buffer + int enc = BassWma.BASS_WMA_EncodeOpenFile(44100, 2, BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, + 128000, "output.wma"); + while (Bass.BASS_ChannelIsActive(stream) == BASSActive.BASS_ACTIVE_PLAYING) + { + int len = Bass.BASS_ChannelGetData(stream, buffer, 16384); + if (len > 0) + BassWma.BASS_WMA_EncodeWrite(enc, buffer, len); + } + BassWma.BASS_WMA_EncodeClose(enc); + } + + + Dim stream As Integer = Bass.BASS_StreamCreateFile("input.mp3", 0L, 0L, BASSFlag.BASS_STREAM_DECODE) + If stream <> 0 Then + Dim buffer(16384 - 1) As Byte ' 16KB decode buffer + Dim enc As Integer = BassWma.BASS_WMA_EncodeOpenFile(44100, 2, BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, + 128000, "output.wma") + While Bass.BASS_ChannelIsActive(stream) = BASSActive.BASS_ACTIVE_PLAYING + Dim len As Integer = Bass.BASS_ChannelGetData(stream, buffer, 16384) + If len > 0 Then + BassWma.BASS_WMA_EncodeWrite(enc, buffer, len) + End If + End While + BassWma.BASS_WMA_EncodeClose(enc) + End If + + + + + + Initializes WMA encoding to the network. + + The sample rate in Hz. + The number of channels (1=mono, 2=stereo, etc.). + Any combination of these flags (see ): + + BASS_SAMPLE_8BITS8-bit sample data. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then 16-bit data is expected. + BASS_SAMPLE_FLOAT32-bit floating-point sample data. + BASS_WMA_ENCODE_STANDARDUse standard WMA encoding. If neither this or the BASS_WMA_ENCODE_PRO flag is specified, then either codec could be used (whichever supports the requested sample format and bitrate). + BASS_WMA_ENCODE_PROUse WMA Professional encoding. + BASS_WMA_ENCODE_PCMWrite uncompressed PCM data in an ASF container. bitrate is ignored except that it should be non-0. + BASS_WMA_ENCODE_24BITEncode in 24-bit, else 16-bit. 24-bit encoding requires WMA Pro. + BASS_WMA_ENCODE_SCRIPTEnable the specification of tags mid-stream (after encoding has begun). + + + The encoding bitrate (in bits per second, e.g. 128000), or VBR quality (100 or less). + The port number for clients to conenct to... 0 = let the system choose a port. + The maximum number of clients (up to 50) that can be connected. + If succesful, the new encoder's handle is returned, else 0 is returned. Use to get the error code. + + If you chose to let the system select a port, you can retrieve the port number using . + The WMA codec expects 16-bit or 24-bit sample data depending on the BASS_WMA_ENCODE_24BIT flag, but BASSWMA will accept 8-bit, 16-bit or floating-point data, and convert it to the appropriate format. Use to retrieve a list of the encoding bitrates available for a specific sample format. + VBR encoding is not recommended for network encoding. + Use for each tag you wish to set. + Use to encode sample data, and to finish encoding and close the network port. + + + ERROR CODEDescription + BASS_ERROR_WMAThe Windows Media modules (v9 or above) are not installed. + BASS_ERROR_ILLPARAM is invalid. + BASS_ERROR_NOTAVAILNo codec could be found to support the specified sample format and bitrate. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + Stream what you are recording using a system-chosen port, and allowing up to 5 clients: + + private RECORDPROC _myRecProc; + ... + if ( Bass.BASS_RecordInit(-1) ) + { + int enc = BassWma.BASS_WMA_EncodeOpenNetwork(44100, 2, BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, + 128000, 0, 5); + _myRecProc = new RECORDPROC(MyRecording); + int recHandle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_DEFAULT, _myRecProc, new IntPtr(enc)); + } + ... + private bool MyRecording(int handle, IntPtr buffer, int length, IntPtr user) + { + if (length > 0 && buffer != IntPtr.Zero) + { + // write the recorded data to the encoder + BassWma.BASS_WMA_EncodeWrite(user.ToInt32(), buffer, length); + } + return true; + } + + + Private _myRecProc As RECORDPROC + ... + If Bass.BASS_RecordInit(-1) Then + Dim enc As Integer = BassWma.BASS_WMA_EncodeOpenNetwork(44100, 2, BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, + 128000, 0, 5) + _myRecProc = New RECORDPROC(AddressOf MyRecording) + Dim recHandle As Integer = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_DEFAULT, _myRecProc, New IntPtr(enc)) + End If + ... + Private Function MyRecording(handle As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Boolean + If length > 0 AndAlso buffer <> IntPtr.Zero Then + ' write the recorded data to the encoder + BassWma.BASS_WMA_EncodeWrite(user.ToInt32(), buffer, length) + End If + Return True + End Function + + + + + + Initializes WMA encoding to the network, using multiple bitrates. + + The sample rate in Hz. + The number of channels (1=mono, 2=stereo, etc.). + Any combination of these flags (see ): + + BASS_SAMPLE_8BITS8-bit sample data. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then 16-bit data is expected. + BASS_SAMPLE_FLOAT32-bit floating-point sample data. + BASS_WMA_ENCODE_STANDARDUse standard WMA encoding. If neither this or the BASS_WMA_ENCODE_PRO flag is specified, then either codec could be used (whichever supports the requested sample format and bitrate). + BASS_WMA_ENCODE_PROUse WMA Professional encoding. + BASS_WMA_ENCODE_PCMWrite uncompressed PCM data in an ASF container. bitrate is ignored except that it should be non-0. + BASS_WMA_ENCODE_24BITEncode in 24-bit, else 16-bit. 24-bit encoding requires WMA Pro. + BASS_WMA_ENCODE_SCRIPTEnable the specification of tags mid-stream (after encoding has begun). + + + Array of encoding bitrates (in bits per second, e.g. 128000) to use, terminated with a 0 element (so the number of elements in the array must be one more than the effective bitrates used). + The port number for clients to conenct to... 0 = let the system choose a port. + The maximum number of clients (up to 50) that can be connected. + If succesful, the new encoder's handle is returned, else is returned. Use to get the error code. + This function is identical to , but with the additional ability to specify multiple bitrates. + When encoding/broadcasting in multiple bitrates, the user will automatically get the best available bitrate for their bandwidth. + The WMA codec expects 16-bit or 24-bit sample data depending on the BASS_WMA_ENCODE_24BIT flag, but BASSWMA will accept 8-bit, 16-bit or floating-point data, and convert it to the appropriate format. Use to retrieve a list of the encoding bitrates available for a specific sample format. + VBR encoding is not recommended for network encoding. + + + ERROR CODEDescription + BASS_ERROR_WMAThe Windows Media modules (v9 or above) are not installed. + BASS_ERROR_ILLPARAM is invalid. + BASS_ERROR_NOTAVAILNo codec could be found to support the specified sample format and bitrate. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Initialize encoding 44100hz 16-bit stereo sample data at 128kb/s and 64kb/s, using port 4711, and allowing up to 5 clients. + + int[] bitrates = {128000, 64000, 0}; // the bitrates + int encoder = BassWma.BASS_WMA_EncodeOpenNetworkMulti( 44100, 2, + BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, bitrates, 4711, 5); + + + Dim bitrates As Integer() = {128000, 64000, 0} ' the bitrates + Dim encoder As Integer = BassWma.BASS_WMA_EncodeOpenNetworkMulti(44100, 2, + BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, bitrates, 4711, 5) + + + + + + Unicode + + + + + + + + + + + + + Initializes WMA encoding to a publishing point on a Windows Media server. + This overload implements the Unicode version for url, user and pass. BASS_UNICODE will automatically be added if not set. + + The sample rate in Hz. + The number of channels (1=mono, 2=stereo, etc.). + Any combination of these flags (see ): + + BASS_SAMPLE_8BITS8-bit sample data. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then 16-bit data is expected. + BASS_SAMPLE_FLOAT32-bit floating-point sample data. + BASS_WMA_ENCODE_STANDARDUse standard WMA encoding. If neither this or the BASS_WMA_ENCODE_PRO flag is specified, then either codec could be used (whichever supports the requested sample format and bitrate). + BASS_WMA_ENCODE_PROUse WMA Professional encoding. + BASS_WMA_ENCODE_PCMWrite uncompressed PCM data in an ASF container. bitrate is ignored except that it should be non-0. + BASS_WMA_ENCODE_24BITEncode in 24-bit, else 16-bit. 24-bit encoding requires WMA Pro. + BASS_WMA_ENCODE_SCRIPTEnable the specification of tags mid-stream (after encoding has begun). + + + The encoding bitrate (in bits per second, e.g. 128000), or VBR quality (100 or less). + URL of the publishing point on the Windows Media server. + Username to use in connecting to the server... if either this or pass is , then no username/password is sent to the server. + Password to use in connecting to the server. + If succesful, the new encoder's handle is returned, else 0 is returned. Use to get the error code. + + The WMA codec expects 16-bit or 24-bit sample data depending on the BASS_WMA_ENCODE_24BIT flag, but BASSWMA will accept 8-bit, 16-bit or floating-point data, and convert it to the appropriate format. Use to retrieve a list of the encoding bitrates available for a specific sample format. + VBR encoding is not recommended for network encoding. + Use for each tag you wish to set. + Use to encode sample data, and to finish encoding and close the network port. + + + ERROR CODEDescription + BASS_ERROR_WMAThe Windows Media modules (v9 or above) are not installed. + BASS_ERROR_NOTAVAILNo codec could be found to support the requested sample format and bitrate. + BASS_ERROR_FILEOPENCould not connect to the server. + BASS_ERROR_WMA_DENIEDAccess was denied. Check the and . + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Unicode + + + + + + + + + + + + + Initializes WMA encoding to a publishing point on a Windows Media server, using multiple bitrates. + This overload implements the Unicode version for url, user and pass. BASS_UNICODE will automatically be added if not set. + + The sample rate in Hz. + The number of channels (1=mono, 2=stereo, etc.). + Any combination of these flags (see ): + + BASS_SAMPLE_8BITS8-bit sample data. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then 16-bit data is expected. + BASS_SAMPLE_FLOAT32-bit floating-point sample data. + BASS_WMA_ENCODE_STANDARDUse standard WMA encoding. If neither this or the BASS_WMA_ENCODE_PRO flag is specified, then either codec could be used (whichever supports the requested sample format and bitrate). + BASS_WMA_ENCODE_PROUse WMA Professional encoding. + BASS_WMA_ENCODE_PCMWrite uncompressed PCM data in an ASF container. bitrate is ignored except that it should be non-0. + BASS_WMA_ENCODE_24BITEncode in 24-bit, else 16-bit. 24-bit encoding requires WMA Pro. + BASS_WMA_ENCODE_SCRIPTEnable the specification of tags mid-stream (after encoding has begun). + + + Array of encoding bitrates to use, terminated with a 0 (in bits per second, e.g. 128000). + URL of the publishing point on the Windows Media server. + Username to use in connecting to the server... if either this or pass is , then no username/password is sent to the server. + Password to use in connecting to the server. + If succesful, the new encoder's handle is returned, else 0 is returned. Use to get the error code. + + This function is identical to BASS_WMA_EncodeOpenPublish, but with the additional ability to specify multiple bitrates. + When encoding/broadcasting in multiple bitrates, the user will automatically get the best available bitrate for their bandwidth. + The WMA codec expects 16-bit or 24-bit sample data depending on the BASS_WMA_ENCODE_24BIT flag, but BASSWMA will accept 8-bit, 16-bit or floating-point data, and convert it to the appropriate format. Use to retrieve a list of the encoding bitrates available for a specific sample format. + VBR encoding is not recommended for network encoding. + Use for each tag you wish to set. + Use to encode sample data, and to finish encoding and close the network port. + + + ERROR CODEDescription + BASS_ERROR_WMAThe Windows Media modules (v9 or above) are not installed. + BASS_ERROR_NOTAVAILNo codec could be found to support the requested sample format and bitrate. + BASS_ERROR_FILEOPENCould not connect to the server. + BASS_ERROR_WMA_DENIEDAccess was denied. Check the and . + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Retrieves the network port for clients to connect to. + + The encoder handle. + If succesful, the port number is returned, else 0 is returned. Use to get the error code. + + If you have choosen to let the system select a port (e.g. in your or ), + this is the function to retrieve the port actually being used. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe encoder is not a network encoder, so no port is being used. + + + + + + + Sets a client connection notification callback on a network encoder. + + The encoder handle. + User defined notification function... = disable notifications. + User instance data to pass to the callback function. + If succesful, is returned, else is returned. Use to get the error code. + A previously set notification callback can be changed (or removed) at any time, by calling this function again. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe encoder is not a network encoder, so no port is being used. + + + + + + private CLIENTCONNECTPROC _myClientConnectProc; + ... + // set the notification callback + _myClientConnectProc = new CLIENTCONNECTPROC(MyClientConnectNotify); + BassWma.BASS_WMA_EncodeSetNotify(encoder, _myClientConnectProc, IntPtr.Zero); + ... + // the recording callback + private void MyClientConnectNotify(int handle, bool connect, string ip, IntPtr user) + { + if (connect) + Console.Writeln( "Connected: {0} at {1}", ip, DateTime.Now ); + else + Console.Writeln( "Disconnected: {0} at {1}", ip, DateTime.Now ); + } + + + Private _myClientConnectProc As CLIENTCONNECTPROC + ... + ' set the notification callback + _myClientConnectProc = New CLIENTCONNECTPROC(AddressOf MyClientConnectNotify) + BassWma.BASS_WMA_EncodeSetNotify(encoder, _myClientConnectProc, IntPtr.Zero) + ... + ' the recording callback + Private Sub MyClientConnectNotify(handle As Integer, connect As Boolean, ip As String, user As IntPtr) + If connect Then + Console.Writeln("Connected: {0} at {1}", ip, DateTime.Now) + Else + Console.Writeln("Disconnected: {0} at {1}", ip, DateTime.Now) + End If + End Sub + + + + + + Retrieves the number of clients currently connected to the encoder. + + The encoder handle. + If succesful, the number of clients is returned, else -1 is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe encoder was not created with . + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Sets a tag in a WMA encoding. + + The encoder handle. + The pointer to the tag to set. + The pointer to the tag's text/data. + The format of the tag and value strings. One of the following (see ): + + BASS_WMA_TAG_ANSIANSI strings. + BASS_WMA_TAG_UNICODEUnicode (UTF-16) strings. + BASS_WMA_TAG_UTF8UTF-8 strings. + + + If succesful, is returned, else is returned. Use to get the error code. + Where the tags are located in the encoded stream depends on when this function is used. Calling this function before beginning encoding data puts the tags in the stream's header. Calling this function after encoding has begun puts the tags in the actual stream data, at the current encoding position. + Header tags must be set before encoding any data - no more header tags can be set once has been called. + To set tags mid-stream (after encoding has begun), the BASS_WMA_ENCODE_SCRIPT flag needs to have been specified in the encoder's creation. A mid-stream tag typically used is "Caption", which get's displayed in Windows Media Player 9 and above (if the user has enabled captions). + When using a network encoder, it should be noted that while all header tags are sent to newly connecting clients, prior mid-stream tags are not. So if, for example, you're using the "Caption" tag to indicate the current song title, it should be sent at fairly regular intervals (not only at the start of the song). + On the playback side, mid-stream tags can be processed using (with BASS_TAG_WMA_META). + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe encoder does not have mid-stream tags enabled, so tags can not be set once encoding has begun. + BASS_ERROR_ILLPARAM and/or is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Initialize encoding 44100hz 16-bit stereo sample data at 128kbps to a file called "out.wma", + and set the header tag "Title" to "Something". + + int encoder = BassWma.BASS_WMA_EncodeOpenFile(44100, 2, + BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, 128000, "out.wma"); + // set the title tag + BassWma.BASS_WMA_EncodeSetTag(encoder, "Title", "Something", BASSWMATag.BASS_WMA_TAG_UNICODE); + + + Dim encoder As Integer = BassWma.BASS_WMA_EncodeOpenFile(44100, 2, + BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, 128000, "out.wma") + ' set the title tag + BassWma.BASS_WMA_EncodeSetTag(encoder, "Title", "Something", BASSWMATag.BASS_WMA_TAG_UNICODE) + + + + + + + + + + + + + + + + Sets a tag in a WMA encoding. + + The encoder handle. + The tag to set. + The standard WMA header tags are as follows: + + TitleContent title. + AuthorName of the content author (Artist). + DescriptionDescription of the content. + RatingContent rating. + CopyrightContent copyright message. + WM/AlbumTitleAlbum title. + WM/PromotionURLURL to an HTML page containing related information. + WM/AlbumCoverURLURL to an HTML page containing an image of the album cover. + WM/GenreGenre of the music. + WM/YearYear of publication of the music. + + + The tag's text/data. + The format of the tag and value strings. One of the following (see ): + + BASS_WMA_TAG_ANSIANSI strings (actually not used and automatically converted to BASS_WMA_TAG_UNICODE). + BASS_WMA_TAG_UNICODEUnicode (UTF-16) strings (recommended for .Net). + BASS_WMA_TAG_UTF8UTF-8 strings. + + You don't actually need to set any flags here, since we automatically add the BASS_WMA_TAG_UNICODE flag, unless you explititly set the BASS_WMA_TAG_UTF8 flag. + + If succesful, is returned, else is returned. Use to get the error code. + Where the tags are located in the encoded stream depends on when this function is used. Calling this function before beginning encoding data puts the tags in the stream's header. Calling this function after encoding has begun puts the tags in the actual stream data, at the current encoding position. + Header tags must be set before encoding any data - no more header tags can be set once has been called. + To set tags mid-stream (after encoding has begun), the BASS_WMA_ENCODE_SCRIPT flag needs to have been specified in the encoder's creation. A mid-stream tag typically used is "Caption", which get's displayed in Windows Media Player 9 and above (if the user has enabled captions). + When using a network encoder, it should be noted that while all header tags are sent to newly connecting clients, prior mid-stream tags are not. So if, for example, you're using the "Caption" tag to indicate the current song title, it should be sent at fairly regular intervals (not only at the start of the song). + On the playback side, mid-stream tags can be processed using (with BASS_SYNC_META). + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe encoder does not have mid-stream tags enabled, so tags can not be set once encoding has begun. + BASS_ERROR_ILLPARAM and/or is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Initialize encoding 44100hz 16-bit stereo sample data at 128kbps to a file called "out.wma", + and set the header tag "Title" to "Something" in UTF-8 format. + + int encoder = BassWma.BASS_WMA_EncodeOpenFile(44100, 2, + BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, 128000, "out.wma"); + // set the title tag + BassWma.BASS_WMA_EncodeSetTag(encoder, "Title", "Something", BASSWMATag.BASS_WMA_TAG_UTF8); + + + Dim encoder As Integer = BassWma.BASS_WMA_EncodeOpenFile(44100, 2, + BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, 128000, "out.wma") + ' set the title tag + BassWma.BASS_WMA_EncodeSetTag(encoder, "Title", "Something", BASSWMATag.BASS_WMA_TAG_UTF8) + + + + + + + + + + + + + + + + Sets a binary tag in a WMA encoding. + + The encoder handle. + The tag to set (e.g. "WM/Picture"). + The number of bytes provided as binary data in the tag. + The pointer to the binary tag's data. + If succesful, is returned, else is returned. Use to get the error code. + Where the tags are located in the encoded stream depends on when this function is used. Calling this function before beginning encoding data puts the tags in the stream's header. Calling this function after encoding has begun puts the tags in the actual stream data, at the current encoding position. + Header tags must be set before encoding any data - no more header tags can be set once has been called. + To set tags mid-stream (after encoding has begun), the BASS_WMA_ENCODE_SCRIPT flag needs to have been specified in the encoder's creation. A mid-stream tag typically used is "Caption", which get's displayed in Windows Media Player 9 and above (if the user has enabled captions). + When using a network encoder, it should be noted that while all header tags are sent to newly connecting clients, prior mid-stream tags are not. So if, for example, you're using the "Caption" tag to indicate the current song title, it should be sent at fairly regular intervals (not only at the start of the song). + On the playback side, mid-stream tags can be processed using (with BASS_SYNC_META). + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe encoder does not have mid-stream tags enabled, so tags can not be set once encoding has begun. + BASS_ERROR_ILLPARAM and/or is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Sets a tag in a WMA encoding (Unicode version). + + The encoder handle. + The tag to set. + The standard WMA header tags are as follows: + + TitleContent title. + AuthorName of the content author (Artist). + DescriptionDescription of the content. + RatingContent rating. + CopyrightContent copyright message. + WM/AlbumTitleAlbum title. + WM/PromotionURLURL to an HTML page containing related information. + WM/AlbumCoverURLURL to an HTML page containing an image of the album cover. + WM/GenreGenre of the music. + WM/YearYear of publication of the music. + + + The tag's text/data. + If succesful, is returned, else is returned. Use to get the error code. + Where the tags are located in the encoded stream depends on when this function is used. Calling this function before beginning encoding data puts the tags in the stream's header. Calling this function after encoding has begun puts the tags in the actual stream data, at the current encoding position. + Header tags must be set before encoding any data - no more header tags can be set once has been called. + To set tags mid-stream (after encoding has begun), the BASS_WMA_ENCODE_SCRIPT flag needs to have been specified in the encoder's creation. A mid-stream tag typically used is "Caption", which get's displayed in Windows Media Player 9 and above (if the user has enabled captions). + When using a network encoder, it should be noted that while all header tags are sent to newly connecting clients, prior mid-stream tags are not. So if, for example, you're using the "Caption" tag to indicate the current song title, it should be sent at fairly regular intervals (not only at the start of the song). + On the playback side, mid-stream tags can be processed using (with BASS_SYNC_META). + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe encoder does not have mid-stream tags enabled, so tags can not be set once encoding has begun. + BASS_ERROR_ILLPARAM and/or is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Initialize encoding 44100hz 16-bit stereo sample data at 128kbps to a file called "out.wma", + and set the header tag "Title" to "Something". + + int encoder = BassWma.BASS_WMA_EncodeOpenFile(44100, 2, + BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, 128000, "out.wma"); + // set the title tag + BassWma.BASS_WMA_EncodeSetTag(encoder, "Title", "Something"); + + + Dim encoder As Integer = BassWma.BASS_WMA_EncodeOpenFile(44100, 2, + BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, 128000, "out.wma") + ' set the title tag + BassWma.BASS_WMA_EncodeSetTag(encoder, "Title", "Something") + + + + + + Encodes sample data, and writes it to the file or network. + This overload uses an IntPtr to point to the memory block containing the data. + + The encoder handle. + The buffer containing the sample data. + The number of BYTES in the buffer. + If succesful, is returned, else is returned. Use to get the error code. + The WMA codec expects 16-bit or 24-bit sample data depending on the BASS_WMA_ENCODE_24BIT flag, but BASSWMA will accept 8-bit, 16-bit or floating-point data, and convert it to the appropriate format. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + Stream what you are recording using a system-chosen port, and allowing up to 5 clients: + + private RECORDPROC _myRecProc; + ... + if ( Bass.BASS_RecordInit(-1) ) + { + int enc = BassWma.BASS_WMA_EncodeOpenNetwork(44100, 2, BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, + 128000, 0, 5); + _myRecProc = new RECORDPROC(MyRecording); + int recHandle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_DEFAULT, _myRecProc, new IntPtr(enc)); + } + ... + private bool MyRecording(int handle, IntPtr buffer, int length, IntPtr user) + { + if (length > 0 && buffer != IntPtr.Zero) + { + // write the recorded data to the encoder + BassWma.BASS_WMA_EncodeWrite(user.ToInt32(), buffer, length); + } + return true; + } + + + Private _myRecProc As RECORDPROC + ... + If Bass.BASS_RecordInit(-1) Then + Dim enc As Integer = BassWma.BASS_WMA_EncodeOpenNetwork(44100, 2, BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, + 128000, 0, 5) + _myRecProc = New RECORDPROC(AddressOf MyRecording) + Dim recHandle As Integer = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_DEFAULT, _myRecProc, New IntPtr(enc)) + End If + ... + Private Function MyRecording(handle As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Boolean + If length > 0 AndAlso buffer <> IntPtr.Zero Then + ' write the recorded data to the encoder + BassWma.BASS_WMA_EncodeWrite(user.ToInt32(), buffer, length) + End If + Return True + End Function + + + + + + Encodes sample data, and writes it to the file or network. + This overload uses a managed float[] to handover sample data to the encoder. + + The encoder handle. + The buffer containing the sample data. + The number of BYTES in the buffer. + If succesful, is returned, else is returned. Use to get the error code. + The WMA codec expects 16-bit or 24-bit sample data depending on the BASS_WMA_ENCODE_24BIT flag, but BASSWMA will accept 8-bit, 16-bit or floating-point data, and convert it to the appropriate format. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + See the overload taking a byte array for an example. + + + + Encodes sample data, and writes it to the file or network. + This overload uses a managed int[] to handover sample data to the encoder (Note: An int[] is 32-bit. When using 16-bit samples we can keep a stereo pair in here). + + The encoder handle. + The buffer containing the sample data. + The number of BYTES in the buffer. + If succesful, is returned, else is returned. Use to get the error code. + The WMA codec expects 16-bit or 24-bit sample data depending on the BASS_WMA_ENCODE_24BIT flag, but BASSWMA will accept 8-bit, 16-bit or floating-point data, and convert it to the appropriate format. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + See the overload taking a byte array for an example. + + + + Encodes sample data, and writes it to the file or network. + This overload uses a managed short[] to handover sample data to the encoder (perfect for 16-bit samples). + + The encoder handle. + The buffer containing the sample data. + The number of BYTES in the buffer. + If succesful, is returned, else is returned. Use to get the error code. + The WMA codec expects 16-bit or 24-bit sample data depending on the BASS_WMA_ENCODE_24BIT flag, but BASSWMA will accept 8-bit, 16-bit or floating-point data, and convert it to the appropriate format. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + See the overload taking a byte array for an example. + + + + Encodes sample data, and writes it to the file or network. + This overload uses a managed byte[] to handover sample data to the encoder (perfect for 8-bit samples). + + The encoder handle. + The buffer containing the sample data. + The number of BYTES in the buffer. + If succesful, is returned, else is returned. Use to get the error code. + The WMA codec expects 16-bit or 24-bit sample data depending on the BASS_WMA_ENCODE_24BIT flag, but BASSWMA will accept 8-bit, 16-bit or floating-point data, and convert it to the appropriate format. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Initialize encoding 44100hz 16-bit stereo sample data at 128kb/s to a file called "output.wma": + + int stream = Bass.BASS_StreamCreateFile("input.mp3", 0L, 0L, BASSFlag.BASS_STREAM_DECODE); + if (stream != 0) + { + byte[] buffer = new byte[16384]; // 16KB decode buffer + int enc = BassWma.BASS_WMA_EncodeOpenFile(44100, 2, BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, + 128000, "output.wma"); + while (Bass.BASS_ChannelIsActive(stream) == BASSActive.BASS_ACTIVE_PLAYING) + { + int len = Bass.BASS_ChannelGetData(stream, buffer, 16384); + if (len > 0) + BassWma.BASS_WMA_EncodeWrite(enc, buffer, len); + } + BassWma.BASS_WMA_EncodeClose(enc); + } + + + Dim stream As Integer = Bass.BASS_StreamCreateFile("input.mp3", 0L, 0L, BASSFlag.BASS_STREAM_DECODE) + If stream <> 0 Then + Dim buffer(16384 - 1) As Byte ' 16KB decode buffer + Dim enc As Integer = BassWma.BASS_WMA_EncodeOpenFile(44100, 2, BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, + 128000, "output.wma") + While Bass.BASS_ChannelIsActive(stream) = BASSActive.BASS_ACTIVE_PLAYING + Dim len As Integer = Bass.BASS_ChannelGetData(stream, buffer, 16384) + If len > 0 Then + BassWma.BASS_WMA_EncodeWrite(enc, buffer, len) + End If + End While + BassWma.BASS_WMA_EncodeClose(enc) + End If + + + + + + Finishes encoding and closes the file or network port. + + The encoder handle. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + > + + + + + Supported file extensions of the basswma.dll + + + + + Supported file format name of the basswma.dll + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + The disadvantage of this method is, that the standard plugin support for is not working - so you would need to use the native add-on methods! + + + Load BASS and BASSWMA from the application's startup path: + + Bass.LoadMe(); + BassWma.LoadMe(); + ... + // when not used anymore... + BassWma.FreeMe(); + Bass.FreeMe(); + + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + Load BASS and BASSWMA from a different directory: + + Bass.LoadMe( @"C:\Development\BASS\_libs" ); + BassWma.LoadMe( @"C:\Development\BASS\_libs" ); + ... + // when not used anymore... + BassWma.FreeMe(); + Bass.FreeMe(); + + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + Return , if this version is a WMA DRM version - else . + + + + + WMA encoding flags for use with , , , or . + + + + + Default encoding, no tags. + + + + + 8 bit sample data. + + + + + 32-bit floating-point sample data. + + + + + Standard WMA encoding. + + + + + WMA Professional encoding. + + + + + Enable 24-bit encoding. + + + + + Save uncompressed PCM data. + When the sample data is floating-point (BASS_SAMPLE_FLOAT flag is used), the BASS_WMA_ENCODE_24BIT flag is considered; 24-bit data is written with it and 16-bit without. The "bitrate" parameter is ignored, except that it should be non-0. + + + + + Enable the specification of tags mid-stream (after encoding has begun). + + + + + GetRates: get available VBR quality settings. + + + + + GetRates: get available CBR quality settings. + + + + + file is a Unicode (16-bit characters) filename. + + + + + WMA encoding callback flags for use with . + + + + + The data in the buffer is the header. + + + + + The data in the buffer is encoded sample data. + + + + + The encoding has finished... buffer and length will both be resp. 0. + + + + + The "type" of the tag and values strings for use with . + + + + + ANSI strings. + + + + + Unicode (UTF-16) strings (recommended to be used with .Net). + + + + + UTF-8 strings. + + + + + Write a binary tag. + When using that flag, the length of the binary data is given in the high word, eg. use Utils.MakeLong((int)BASSWMATag.BASS_WMA_TAG_BINARY, binaryLength). + e.g. call: + + + + + User defined client connection notification callback function. + + The encoder handle (as returned by ). + The client is connecting? + The client's IP address... "xxx.xxx.xxx.xxx:port". + The user instance data given when was called. + + + A client connection notification can be used to keep track of who's connected, where they're from, and for long they've been connected. + + NOTE: When you pass an instance of a callback delegate to one of the BASS functions, this delegate object will not be reference counted. + This means .NET would not know, that it might still being used by BASS. The Garbage Collector might (re)move the delegate instance, if the variable holding the delegate is not declared as global. + So make sure to always keep your delegate instance in a variable which lives as long as BASS needs it, e.g. use a global variable or member. + + + + private CLIENTCONNECTPROC _myClientConnectProc; + ... + // set the notification callback + _myClientConnectProc = new CLIENTCONNECTPROC(MyClientConnectNotify); + BassWma.BASS_WMA_EncodeSetNotify(encoder, _myClientConnectProc, IntPtr.Zero); + ... + // the recording callback + private void MyClientConnectNotify(int handle, bool connect, string ip, IntPtr user) + { + if (connect) + Console.Writeln( "Connected: {0} at {1}", ip, DateTime.Now ); + else + Console.Writeln( "Disconnected: {0} at {1}", ip, DateTime.Now ); + } + + + Private _myClientConnectProc As CLIENTCONNECTPROC + ... + ' set the notification callback + _myClientConnectProc = New CLIENTCONNECTPROC(AddressOf MyClientConnectNotify) + BassWma.BASS_WMA_EncodeSetNotify(encoder, _myClientConnectProc, IntPtr.Zero) + ... + ' the recording callback + Private Sub MyClientConnectNotify(handle As Integer, connect As Boolean, ip As String, user As IntPtr) + If connect Then + Console.Writeln("Connected: {0} at {1}", ip, DateTime.Now) + Else + Console.Writeln("Disconnected: {0} at {1}", ip, DateTime.Now) + End If + End Sub + + + + + + Encoded data processing callback function. + + The encoder handle (as returned by ). + The type of data to process, one of the following (see ): + BASS_WMA_ENCODE_HEAD : The data in the buffer is the header. + BASS_WMA_ENCODE_DATA : The data in the buffer is encoded sample data. + BASS_WMA_ENCODE_DONE : The encoding has finished... buffer and length will both be intPtr.Zero resp. 0. + + The pointer to the data to process. The buffer can contain the sample data or the header (see above). The sample data is in standard Windows PCM format - 8-bit samples are unsigned, 16-bit samples are signed. + The number of bytes in the buffer. + The user instance data given when was called. + + + When encoding begins, an initial header is given. When encoding is completed, an updated header is given (with the duration info, etc.). + When encoding to a file (whether that's on disk or not), the initial header should be replaced by the updated one. + + NOTE: When you pass an instance of a callback delegate to one of the BASS functions, this delegate object will not be reference counted. + This means .NET would not know, that it might still being used by BASS. The Garbage Collector might (re)move the delegate instance, if the variable holding the delegate is not declared as global. + So make sure to always keep your delegate instance in a variable which lives as long as BASS needs it, e.g. use a global variable or member. + + + + // the encoding callback + private WMENCODEPROC _myEndoderProc; + private FileStream _fs; + private byte[] _encbuffer = new byte[1048510]; // 1MB buffer, should be enough + ... + // open a wma file + _fs = File.OpenRead("test.wma"); + // create the encoder (44kHz, stereo at 64kbps, no tags) + _myEndoderProc = new WMENCODEPROC(MyEncodingWriter); + int encoder = BassWma.BASS_WMA_EncodeOpen(44100, 2, BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, + 64000, _myEndoderProc, IntPtr.Zero); + ... + private bool MyEncodingWriter(int handle, BASSWMAEncodeCallback type, IntPtr buffer, int length, IntPtr user) + { + if (type == BASSWMAEncodeCallback.BASS_WMA_ENCODE_HEAD) + { + // rewind to start of file to write the header + _fs.Position = 0L; + } + + if (type == BASSWMAEncodeCallback.BASS_WMA_ENCODE_DONE) + { + // done encoding - close the file + _fs.Flush(); + _fs.Close(); + } + else + { + // copy the unmanaged buffer content to out managed buffer + Marshal.Copy(buffer, _encbuffer, 0, length); + // process the data in _encbuffer + _fs.Write(_encbuffer, 0, length); + } + } + + + Private _myEndoderProc As WMENCODEPROC + Private _fs As FileStream + Private _encbuffer(1048510) As Byte ' 1MB buffer, should be enough + ... + ' open a wma file + _fs = File.OpenRead("test.wma") + ' create the encoder (44kHz, stereo at 64kbps, no tags) + _myEndoderProc = New WMENCODEPROC(AddressOf MyEncodingWriter) + Dim encoder As Integer = BassWma.BASS_WMA_EncodeOpen(44100, 2, BASSWMAEncode.BASS_WMA_ENCODE_DEFAULT, + 64000, _myEndoderProc, IntPtr.Zero) + ... + Private Function MyEncodingWriter(handle As Integer, type As BASSWMAEncodeCallback, + buffer As IntPtr, length As Integer, user As IntPtr) As Boolean + If type = BASSWMAEncodeCallback.BASS_WMA_ENCODE_HEAD Then + ' rewind to start of file to write the header + _fs.Position = 0L.ToUInt32() + End If + + If type = BASSWMAEncodeCallback.BASS_WMA_ENCODE_DONE Then + ' done encoding - close the file + _fs.Flush() + _fs.Close() + Else + ' copy the unmanaged buffer content to out managed buffer + Marshal.Copy(buffer, _encbuffer, 0, length) + ' process the data in _encbuffer + _fs.Write(_encbuffer, 0, length) + End If + End Function + + NOTE: This is just an example. It's obviously simpler to use to encode to a file. + + + + + BASS.NET API wrapper for BASSMIX.DLL + Requires: bassmix.dll - Mixing and resample channels (MIX) Add-On - available @ www.un4seen.com. + A fairly common question is how to mix and/or resample channels. To make that task simple, here's the add-on that'll do it. + + + BASSMIX is an extension to the BASS audio library, enabling the mixing and resampling of streams and channels. + + + + + Current BASSmix version (without minor revision). + + + + + NOT used - all members are static! + + + + + Retrieves the version number of the BASSmix.DLL that is loaded. + + The BASSmix version. For example, 0x02040103 (hex), would be version 2.4.1.3. + There is no guarantee that a previous or future version of BASSmix supports all the BASSmix functions that you are using, so you should always use this function to make sure the correct version is loaded. + It is safe to assume that future minor revisions (indicated in the LOWORD) will be fully compatible. + You might use the global constant to check the major revision. + Note: Calling this method will also automatically load the library into memory. + + + Checking the major version only: + + if ( Utils.HighWord(BassMix.BASS_Mixer_GetVersion()) != BassMix.BASSMIXVERSION ) + { + MessageBox.Show(this, "Wrong BassMix Version!"); + } + + + If Utils.HighWord(BassMix.BASS_Mixer_GetVersion()) <> BassFx.BASSMIXVERSION Then + MessageBox.Show(Me, "Wrong BassMix Version!") + End If + + Checking for full version "2.4.1.3": + + if (BassMix.BASS_Mixer_GetVersion() < Utils.MakeLong(0x0103, 0x0204)) + { + MessageBox.Show(this, "Wrong BassMix Version!"); + } + + + If BassMix.BASS_Mixer_GetVersion() < Utils.MakeLong(&H103, &H204) Then + MessageBox.Show(Me, "Wrong BassMix Version!") + End If + + + + + + Retrieves the version of the BASSmix.DLL that is loaded. + + The number of components to use. The fieldCount ranges from 1 to 4 (major.minor.build.revision). + The BASSmix version (major.minor.build.revision). + There is no guarantee that a previous or future version of BASSmix supports all the BASSmix functions that you are using, so you should always use this function to make sure the correct version is loaded. + It is safe to assume that future minor revisions (indicated in the LOWORD) will be fully compatible. + Note: Calling this method will also automatically load the library into memory. + + + + Version expectedVersion = new Version(2, 4); + if (BassMix.BASS_Mixer_GetVersion(2) < expectedVersion) + { + MessageBox.Show( this, "Wrong BassMix Version!" ); + } + + + Dim expectedVersion As New Version(2, 4) + If BassMix.BASS_Mixer_GetVersion(2) < expectedVersion Then + MessageBox.Show(Me, "Wrong BassMix Version!") + End If + + + + + + Creates a mixer stream. + + The sample rate of the mixer output (e.g. 44100). + The number of channels... 1 = mono, 2 = stereo, 4 = quadraphonic, 6 = 5.1, 8 = 7.1. More than stereo requires WDM drivers (or the BASS_STREAM_DECODE flag) in Windows, and the SPEAKER flags are ignored. + Any combination of these flags (see ): + + BASS_SAMPLE_8BITSProduce 8-bit output. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the stream is 16-bit. + BASS_SAMPLE_FLOATProduce 32-bit floating-point output. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. Note this only applies to playback of the mixer's output - the mixing of the source channels is always performed by BASSmix. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D streams must be mono (chans=1). The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_FXrequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_MIXER_ENDEnd the stream when there are no active (including stalled) source channels, else it's never-ending. + BASS_MIXER_NONSTOPDon't stop producing output when there are no active source channels, else it will be stalled until there are active sources. + BASS_MIXER_RESUMEWhen stalled, resume the mixer immediately upon a new or unpaused source, else it will be resumed at the next update cycle. + BASS_MIXER_POSEXKeep a record of the source positions, making it possible to account for output latency when retrieving a source position. How far back the position record goes is determined by the config option. If this flag is not used and neither is the flag, then the mixer will automatically have a position record of equal length to the setting. + BASS_STREAM_AUTOFREEAutomatically free the stream's resources when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + + + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + Source channels are "plugged" into a mixer using the or functions, and "unplugged" using the function. + Sources can be added and removed at any time, so a mixer does not have a predetermined length and is not applicable. Likewise, seeking is not possible, except to position 0, as described below. + If the mixer output is being played (it is not a decoding channel), then there will be some delay in the effect of adding/removing source channels or changing their attributes being heard. This latency can be reduced by making use of the and config options. + The playback buffer can be flushed by calling (restart = TRUE) or (pos = 0). That can also be done to restart a mixer that has ended. + Unless the BASS_MIXER_END flag is specified, a mixer stream will never end. When there are no sources (or the sources have ended/stalled), it'll produce no output until there's an active source. + That's unless the BASS_MIXER_NONSTOP flag is used, in which case it will produce silent output while there are no active sources. The BASS_MIXER_END and BASS_MIXER_NONSTOP flags can be toggled at any time, using . + Besides mixing channels, a mixer stream can be used as a resampler. In that case the freq parameter would be set the new sample rate, and the source channel's attributes would be left at their defaults. + A mixer stream can also be used to downmix, upmix and generally rearrange channels, using the matrix mixing features. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding streams (BASS_STREAM_DECODE) are allowed when using the "no sound" device. + BASS_ERROR_FREQfreq is out of range. See the minrate and maxrate members of the structure. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported (ie. no WDM drivers). + BASS_ERROR_SPEAKERThe device/drivers do not support the requested speaker(s), or you're attempting to assign a stereo stream to a mono speaker. + BASS_ERROR_MEMThere is insufficent memory. + BASS_ERROR_NO3DCouldn't initialize 3D support for the stream. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Create a new mixer stream at 44kHz, stereo using floats - out of two source streams: + + // this will be the final mixer output stream being played + int mixer = BassMix.BASS_Mixer_StreamCreate(44100, 2, BASSFlag.BASS_SAMPLE_FLOAT ); + // now we need some channels to plug them in...create two decoding sources + int streamA = Bass.BASS_StreamCreateFile("testA.mp3", 0, 0, + BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); + int streamB = Bass.BASS_StreamCreateFile("testB.mp3", 0, 0, + BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); + // finally we plug them into the mixer (no downmix, since we assume the sources to be stereo) + bool okA = BassMix.BASS_Mixer_StreamAddChannel(mixer, streamA, BASSFlag.BASS_DEFAULT); + bool okB = BassMix.BASS_Mixer_StreamAddChannel(mixer, streamB, BASSFlag.BASS_DEFAULT); + // and play it... + Bass.BASS_ChannelPlay(mixer, false); + + + ' this will be the final mixer output stream being played + Dim mixer As Integer = BassMix.BASS_Mixer_StreamCreate(44100, 2, BASSFlag.BASS_SAMPLE_FLOAT) + ' now we need some channels to plug them in...create two decoding sources + Dim streamA As Integer = Bass.BASS_StreamCreateFile("testA.mp3", 0, 0, + BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT) + Dim streamB As Integer = Bass.BASS_StreamCreateFile("testB.mp3", 0, 0, + BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT) + ' finally we plug them into the mixer (no downmix, since we assume the sources to be stereo) + Dim okA As Boolean = BassMix.BASS_Mixer_StreamAddChannel(mixer, streamA, BASSFlag.BASS_DEFAULT) + Dim okB As Boolean = BassMix.BASS_Mixer_StreamAddChannel(mixer, streamB, BASSFlag.BASS_DEFAULT) + ' and play it... + Bass.BASS_ChannelPlay(mixer, False) + + + + + + Plugs a channel into a mixer. + + The mixer handle (created with ). + The handle of the channel to plug into the mixer... a HMUSIC, HSTREAM or HRECORD (e.g. created with ). + Any combination of these flags (see ): + + BASS_MIXER_MATRIXCreates a channel matrix, allowing the source channels to be sent to any of the mixer output channels, at any levels. The matrix can be retrieved and modified via the and functions. The matrix will initially contain a one-to-one mapping, eg. left out = left in, right out = right in, etc... + BASS_MIXER_DOWNMIXDownmix to stereo, or mono if the mixer output is mono. + BASS_MIXER_BUFFERBuffer the sample data, for use by and . This increases memory requirements, so should not be enabled needlessly. The size of the buffer can be controlled via the BASS_CONFIG_MIXER_BUFFER config option. + BASS_MIXER_LIMITLimit the mixer processing to the amount of data available from this source, while the source is active (not ended). If the source stalls, then the mixer will too, rather than continuing to mix other sources, as it would normally do. This flag can only be applied to one source per mixer, so it will automatically be removed from any other source of the same mixer. + BASS_MIXER_NORAMPINDon't ramp-in the start, including after seeking (). This is useful for gap-less playback, where a source channel is intended to seamlessly follow another. This does not affect volume and pan changes, which are always ramped. + BASS_MIXER_PAUSEDon't process the source channel (add it in a paused mode). Use in order to toggle processing of the source channel. + BASS_STREAM_AUTOFREEAutomatically free the source channel when it ends. This allows you to add a channel to a mixer and forget about it, as it will automatically be freed when it has reached the end, or when the source is removed from the mixer or when the mixer is freed. + BASS_SPEAKER_xxxSpeaker assignment flags. + + + If successful, then is returned, else is returned. Use to get the error code. + + Internally, a mixer will use the function to get data from its source channels. + That means that the source channels must be decoding channels (not using a in the case of a recording channel). + Plugging a channel into more than one mixer at a time is not possible because the mixers would be taking data away from each other. + An advantage of this is that there is no need for a mixer's handle to be provided with the channel functions. + It is actually possible to plug a channel into multiple mixers via the use of splitter streams. + Channels are 'unplugged' using the function. Channels are also automatically unplugged when they are freed. + When mixing a channel, the mixer makes use of the channel's attributes (freq/volume/pan), as set with or . + The BASS_CONFIG_CURVE_VOL and BASS_CONFIG_CURVE_PAN config option settings are also used (see ). + If a multi-channel stream has more channels than the mixer output, the extra channels will be discarded. For example, if a 5.1 stream is plugged into a stereo mixer, only the front-left/right channels will be retained. That is unless matrix mixing is used. + The mixer processing is performed in floating-point, so it makes sense (for both quality and efficiency reasons) for the source channels to be floating-point too, though they do not have to be. + It is also more efficient if the source channels have the same sample rate as the mixer output because no sample rate conversion is required then. + When sample rate conversion is required, windowed sinc interpolation is used and the source's attribute determines how many points/samples are used in that, as follows: + 0 (or below) = 4 points, 1 = 8 points, 2 = 16 points, 3 = 32 points, 4 = 64 points, 5 = 128 points, 6 (or above) = 256 points. 8 points are used if the attribute is unavailable (old BASS version). + A higher number of points results in better sound quality (less aliasing and smaller transition band in the low-pass filter), but also higher CPU usage. + + + ERROR CODEDescription + BASS_ERROR_HANDLEAt least one of and is not valid. + BASS_ERROR_DECODE is not a decoding channel. + BASS_ERROR_ALREADY is already plugged into a mixer. It must be unplugged first. + BASS_ERROR_SPEAKERThe mixer does not support the requested speaker(s), or you're attempting to assign a stereo stream to a mono speaker. + + + Platform-specific: + The sample rate conversion processing is limited to 128 points on iOS and Android. The mixer processing is also performed in fixed-point rather than floating-point on Android. + + + Create a new mixer stream at 44kHz, stereo using floats - out of two source streams: + + // this will be the final mixer output stream being played + int mixer = BassMix.BASS_Mixer_StreamCreate(44100, 2, BASSFlag.BASS_SAMPLE_FLOAT ); + // now we need some channels to plug them in...create two decoding sources + int streamA = Bass.BASS_StreamCreateFile("testA.mp3", 0, 0, + BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); + int streamB = Bass.BASS_StreamCreateFile("testB.mp3", 0, 0, + BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); + // finally we plug them into the mixer (no downmix, since we assume the sources to be stereo) + bool okA = BassMix.BASS_Mixer_StreamAddChannel(mixer, streamA, BASSFlag.BASS_DEFAULT); + bool okB = BassMix.BASS_Mixer_StreamAddChannel(mixer, streamB, BASSFlag.BASS_DEFAULT); + // and play it... + Bass.BASS_ChannelPlay(mixer, false); + + + ' this will be the final mixer output stream being played + Dim mixer As Integer = BassMix.BASS_Mixer_StreamCreate(44100, 2, BASSFlag.BASS_SAMPLE_FLOAT) + ' now we need some channels to plug them in...create two decoding sources + Dim streamA As Integer = Bass.BASS_StreamCreateFile("testA.mp3", 0, 0, + BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT) + Dim streamB As Integer = Bass.BASS_StreamCreateFile("testB.mp3", 0, 0, + BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT) + ' finally we plug them into the mixer (no downmix, since we assume the sources to be stereo) + Dim okA As Boolean = BassMix.BASS_Mixer_StreamAddChannel(mixer, streamA, BASSFlag.BASS_DEFAULT) + Dim okB As Boolean = BassMix.BASS_Mixer_StreamAddChannel(mixer, streamB, BASSFlag.BASS_DEFAULT) + ' and play it... + Bass.BASS_ChannelPlay(mixer, False) + + + + + + Plugs a channel into a mixer, optionally delaying the start and limiting the length. + + The mixer handle. + The handle of the channel to plug into the mixer... a HMUSIC, HSTREAM or HRECORD. + Any combination of these flags (see ): + + BASS_MIXER_MATRIXCreates a channel matrix, allowing the source channels to be sent to any of the mixer output channels, at any levels. The matrix can be retrieved and modified via the and functions. The matrix will initially contain a one-to-one mapping, eg. left out = left in, right out = right in, etc... + BASS_MIXER_DOWNMIXDownmix to stereo, or mono if the mixer output is mono. + BASS_MIXER_BUFFERBuffer the sample data, for use by and . This increases memory requirements, so should not be enabled needlessly. The size of the buffer can be controlled via the BASS_CONFIG_MIXER_BUFFER config option. + BASS_MIXER_LIMITLimit the mixer processing to the amount of data available from this source, while the source is active (not ended). If the source stalls, then the mixer will too, rather than continuing to mix other sources, as it would normally do. This flag can only be applied to one source per mixer, so it will automatically be removed from any other source of the same mixer. + BASS_MIXER_NORAMPINDon't ramp-in the start, including after seeking (). This is useful for gap-less playback, where a source channel is intended to seamlessly follow another. This does not affect volume and pan changes, which are always ramped. + BASS_MIXER_PAUSEDon't process the source channel (add it in a paused mode). Use in order to toggle processing of the source channel. + BASS_STREAM_AUTOFREEAutomatically free the source channel when it ends. This allows you to add a channel to a mixer and forget about it, as it will automatically be freed when it has reached the end, or when the source is removed from the mixer or when the mixer is freed. + BASS_SPEAKER_xxxSpeaker assignment flags. + + + Delay (in bytes) before the channel is mixed in. + The maximum amount of data (in bytes) to mix... 0 = no limit. Once this end point is reached, the channel will be removed from the mixer. + If successful, then is returned, else is returned. Use to get the error code. + This function is identical to , but with the additional ability to specify a delay and duration for the channel. + The and parameters relate to the mixer output. So when calculating these values, use the mixer stream's sample format rather than the source channel's. + The start parameter is automatically rounded-down to the nearest sample boundary, while the length parameter is rounded-up to the nearest sample boundary. + + + ERROR CODEDescription + BASS_ERROR_HANDLEAt least one of and is not valid. + BASS_ERROR_DECODE is not a decoding channel. + BASS_ERROR_ALREADY is already plugged into a mixer. It must be unplugged first. + BASS_ERROR_SPEAKERThe mixer does not support the requested speaker(s), or you're attempting to assign a stereo stream to a mono speaker. + + + + + Add a channel to a mixer, delaying the start by 1 second and limiting the duration to 2 seconds: + + long start = Bass.BASS_ChannelSeconds2Bytes(mixer, 1.0); // delay + long length = Bass.BASS_ChannelSeconds2Bytes(mixer, 2.0); // duration + // add the channel + BassMix.BASS_Mixer_StreamAddChannelEx(mixer, channel, 0, start, length); + + + Dim start As Long = Bass.BASS_ChannelSeconds2Bytes(mixer, 1.0) ' delay + Dim length As Long = Bass.BASS_ChannelSeconds2Bytes(mixer, 2.0) ' duration + ' add the channel + BassMix.BASS_Mixer_StreamAddChannelEx(mixer, channel, 0, start, length) + + + + + + Retrieves the immediate sample data (or an FFT representation of it) of a mixer source channel. + This overload uses an IntPtr to reference the buffer data. + + The handle of the mixer source channel (which was add via or or ) beforehand). + Location to write the data as an (can be when handle is a recording channel (HRECORD), to discard the requested amount of data from the recording buffer). + Use "Marshal.AllocCoTaskMem" to allocate a memory buffer, use "Marshal.Copy" to copy the buffer data from unmanaged BASS to your managed code and use "Marshal.FreeCoTaskMem" to free the memory buffer when not needed anymore. + Or make use of a "GCHandle" to receive data to a pinned managed object. + + Number of bytes wanted, and/or the following flags (): + + BASS_DATA_FLOATReturn floating-point sample data. + BASS_DATA_FFT256256 sample FFT (returns 128 floating-point values) + BASS_DATA_FFT512512 sample FFT (returns 256 floating-point values) + BASS_DATA_FFT10241024 sample FFT (returns 512 floating-point values) + BASS_DATA_FFT20482048 sample FFT (returns 1024 floating-point values) + BASS_DATA_FFT40964096 sample FFT (returns 2048 floating-point values) + BASS_DATA_FFT81928192 sample FFT (returns 4096 floating-point values) + BASS_DATA_FFT_INDIVIDUALUse this flag to request separate FFT data for each channel. The size of the data returned (as listed above) is multiplied by the number channels. + BASS_DATA_FFT_NOWINDOWThis flag can be used to prevent a hanning window being applied to the sample data when performing an FFT. + BASS_DATA_AVAILABLEQuery the amount of data the channel has buffered. This flag is primarily of use when recording, and can't be used with decoding channels as they do not have playback buffers. buffer can be when using this flag. + + + If an error occurs, -1 is returned, use to get the error code. + When requesting FFT data, the number of bytes read from the channel (to perform the FFT) is returned. + When requesting sample data, the number of bytes written to buffer will be returned (not necessarily the same as the number of bytes read when using the BASS_DATA_FLOAT flag). + When using the BASS_DATA_AVAILABLE flag, the number of bytes in the channel's buffer is returned. + + + This function is like the standard , but it gets the data from the channel's buffer instead of decoding it from the channel, + which means that the mixer doesn't miss out on any data. In order to do this, the source channel must have buffering enabled, via the BASS_MIXER_BUFFER flag. + If the mixer is a decoding channel, then the channel's most recent data will be returned. Otherwise, the data will be in sync with what is currently being heard from the mixer, unless the buffer is too small so that the currently heard data isn't in it. + The BASS_CONFIG_MIXER_BUFFER config option can be used to set the buffer size. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not plugged into a mixer. + BASS_ERROR_NOTAVAILThe channel does not have buffering (BASS_MIXER_BUFFER) enabled. + + + + + + + Retrieves the immediate sample data (or an FFT representation of it) of a mixer source channel. + This overload uses a managed float[] to reference the buffer data as 32-bit! + SHOULD ONLY BE USED, if the stream was created with BASS_SAMPLE_FLOAT! + + The handle of the mixer source channel (which was add via or or ) beforehand). + The array (float[]) to receive the data, use BASS_SAMPLE_FLOAT when creating the channel stream! + Number of bytes wanted, and/or the following flags (): + + BASS_DATA_FLOATReturn floating-point sample data. + BASS_DATA_FFT256256 sample FFT (returns 128 floating-point values) + BASS_DATA_FFT512512 sample FFT (returns 256 floating-point values) + BASS_DATA_FFT10241024 sample FFT (returns 512 floating-point values) + BASS_DATA_FFT20482048 sample FFT (returns 1024 floating-point values) + BASS_DATA_FFT40964096 sample FFT (returns 2048 floating-point values) + BASS_DATA_FFT81928192 sample FFT (returns 4096 floating-point values) + BASS_DATA_FFT_INDIVIDUALUse this flag to request separate FFT data for each channel. The size of the data returned (as listed above) is multiplied by the number channels. + BASS_DATA_FFT_NOWINDOWThis flag can be used to prevent a hanning window being applied to the sample data when performing an FFT. + BASS_DATA_AVAILABLEQuery the amount of data the channel has buffered. This flag is primarily of use when recording, and can't be used with decoding channels as they do not have playback buffers. buffer can be when using this flag. + + + If an error occurs, -1 is returned, use to get the error code. + When requesting FFT data, the number of bytes read from the channel (to perform the FFT) is returned. + When requesting sample data, the number of bytes written to buffer will be returned (not necessarily the same as the number of bytes read when using the BASS_DATA_FLOAT flag). + When using the BASS_DATA_AVAILABLE flag, the number of bytes in the channel's buffer is returned. + + + This function is like the standard , but it gets the data from the channel's buffer instead of decoding it from the channel, + which means that the mixer doesn't miss out on any data. In order to do this, the source channel must have buffering enabled, via the BASS_MIXER_BUFFER flag. + If the mixer is a decoding channel, then the channel's most recent data will be returned. Otherwise, the data will be in sync with what is currently being heard from the mixer, unless the buffer is too small so that the currently heard data isn't in it. + The BASS_CONFIG_MIXER_BUFFER config option can be used to set the buffer size. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not plugged into a mixer. + BASS_ERROR_NOTAVAILThe channel does not have buffering (BASS_MIXER_BUFFER) enabled. + + + + + + + Retrieves the immediate sample data of a mixer source channel. + This overload uses a managed short[] to reference the buffer data as 16-bit values - each element will represent one channel in this case! + SHOULD ONLY BE USED, if the stream was created WITHOUT BASS_SAMPLE_FLOAT or BASS_SAMPLE_8BITS! + + The handle of the mixer source channel (which was add via or or ) beforehand). + The array (short[]) to receive the data, e.g. when creating the channel stream with default setting, meaning 16-bit samples! + Number of bytes wanted, and/or the following flags (): + + BASS_DATA_AVAILABLEQuery the amount of data the channel has buffered. This flag is primarily of use when recording, and can't be used with decoding channels as they do not have playback buffers. buffer can be when using this flag. + + + If an error occurs, -1 is returned, use to get the error code. + When requesting sample data, the number of bytes written to buffer will be returned (not necessarily the same as the number of bytes read). + When using the BASS_DATA_AVAILABLE flag, the number of bytes in the channel's buffer is returned. + + + This function is like the standard , but it gets the data from the channel's buffer instead of decoding it from the channel, + which means that the mixer doesn't miss out on any data. In order to do this, the source channel must have buffering enabled, via the BASS_MIXER_BUFFER flag. + If the mixer is a decoding channel, then the channel's most recent data will be returned. Otherwise, the data will be in sync with what is currently being heard from the mixer, unless the buffer is too small so that the currently heard data isn't in it. + The BASS_CONFIG_MIXER_BUFFER config option can be used to set the buffer size. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not plugged into a mixer. + BASS_ERROR_NOTAVAILThe channel does not have buffering (BASS_MIXER_BUFFER) enabled. + + + + + + + Retrieves the immediate sample data of a mixer source channel. + This overload uses a managed int[] to reference the buffer data (Note: an int is 32-bit meaning if we expect to receive 16-bit data stereo a single int value will contain 2 x 16-bit, so a full stereo pair of data)! + SHOULD ONLY BE USED, if the stream was created WITHOUT BASS_SAMPLE_FLOAT or BASS_SAMPLE_8BITS! + + The handle of the mixer source channel (which was add via or or ) beforehand). + The array (int[]) to receive the data, e.g. when creating the channel stream with default setting, meaning 16-bit samples, an int value contains 2 channels (left and right)! + Number of bytes wanted, and/or the following flags (): + + BASS_DATA_AVAILABLEQuery the amount of data the channel has buffered. This flag is primarily of use when recording, and can't be used with decoding channels as they do not have playback buffers. buffer can be when using this flag. + + + If an error occurs, -1 is returned, use to get the error code. + When requesting sample data, the number of bytes written to buffer will be returned (not necessarily the same as the number of bytes read when using the BASS_DATA_FLOAT flag). + When using the BASS_DATA_AVAILABLE flag, the number of bytes in the channel's buffer is returned. + + + This function is like the standard , but it gets the data from the channel's buffer instead of decoding it from the channel, + which means that the mixer doesn't miss out on any data. In order to do this, the source channel must have buffering enabled, via the BASS_MIXER_BUFFER flag. + If the mixer is a decoding channel, then the channel's most recent data will be returned. Otherwise, the data will be in sync with what is currently being heard from the mixer, unless the buffer is too small so that the currently heard data isn't in it. + The BASS_CONFIG_MIXER_BUFFER config option can be used to set the buffer size. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not plugged into a mixer. + BASS_ERROR_NOTAVAILThe channel does not have buffering (BASS_MIXER_BUFFER) enabled. + + + + + + + Retrieves the immediate sample data of a mixer source channel. + This overload uses a managed byte[] to reference the buffer data! + SHOULD ONLY BE USED, if the stream was created with BASS_SAMPLE_8BITS! + + The handle of the mixer source channel (which was add via or or ) beforehand). + The array (byte[]) to receive the data, e.g. when creating the channel with BASS_SAMPLE_8BITS! + Number of bytes wanted, and/or the following flags (): + + BASS_DATA_AVAILABLEQuery the amount of data the channel has buffered. This flag is primarily of use when recording, and can't be used with decoding channels as they do not have playback buffers. buffer can be when using this flag. + + + If an error occurs, -1 is returned, use to get the error code. + When requesting sample data, the number of bytes written to buffer will be returned (not necessarily the same as the number of bytes read when using the BASS_DATA_FLOAT flag). + When using the BASS_DATA_AVAILABLE flag, the number of bytes in the channel's buffer is returned. + + + This function is like the standard , but it gets the data from the channel's buffer instead of decoding it from the channel, + which means that the mixer doesn't miss out on any data. In order to do this, the source channel must have buffering enabled, via the BASS_MIXER_BUFFER flag. + If the mixer is a decoding channel, then the channel's most recent data will be returned. Otherwise, the data will be in sync with what is currently being heard from the mixer, unless the buffer is too small so that the currently heard data isn't in it. + The BASS_CONFIG_MIXER_BUFFER config option can be used to set the buffer size. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not plugged into a mixer. + BASS_ERROR_NOTAVAILThe channel does not have buffering (BASS_MIXER_BUFFER) enabled. + + + + + + + Retrieves the level (peak amplitude) of a mixer source channel. + + The handle of the mixer source channel (which was add via or or ) beforehand). + If an error occurs, -1 is returned, use to get the error code. + If successful, the level of the left channel is returned in the low word (low 16-bits, use ), and the level of the right channel is returned in the high word (high 16-bits, use ). If the channel is mono, then the low word is duplicated in the high word. + The level ranges linearly from 0 (silent) to 32768 (max). 0 will be returned when a channel is stalled. + + + This function is like the standard , but it gets the level from the channel's buffer instead of decoding data from the channel, which means that the mixer doesn't miss out on any data. + In order to do this, the source channel must have buffering enabled, via the BASS_MIXER_BUFFER flag. + If the mixer is a decoding channel, then the channel's most recent data will be used to get the level. Otherwise, the level will be in sync with what is currently being heard from the mixer, unless the buffer is too small so that the currently heard data isn't in it. + The BASS_CONFIG_MIXER_BUFFER config option can be used to set the buffer size. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not plugged into a mixer. + BASS_ERROR_NOTAVAILThe channel does not have buffering (BASS_MIXER_BUFFER) enabled. + BASS_ERROR_NOPLAYThe mixer is not playing. + + + + + Get the left and right levels of a stereo channel: + + BassMix.BASS_Mixer_StreamAddChannel(mixer, channel, BASSFlag.BASS_MIXER_BUFFER); + int level = BassMix.BASS_Mixer_ChannelGetLevel(channel); + int left = Utils.LowWord32(level); // the left level + int right = Utils.HighWord32(level); // the right level + + + BassMix.BASS_Mixer_StreamAddChannel(mixer, channel, BASSFlag.BASS_MIXER_BUFFER) + Dim level As Integer = BassMix.BASS_Mixer_ChannelGetLevel(channel) + Dim left As Integer = Utils.LowWord32(level) ' the left level + Dim right As Integer = Utils.HighWord32(level) ' the right level + + + + + + Retrieves the level (peak amplitude) of a mixer source channel. + + The handle of the mixer source channel (which was add via or or ) beforehand). + The array which will receive the peak levels values. The size of the array must be set to the number of channels of the stream (e.g. 2 for stereo). + On success is returned - else , use to get the error code. + If successful, the peak levels of the interleaved channel order is returned in the array. + The level value ranges linearly from 0.0 (silent) to 1.0 (=0dB) or above. + + + This function is like the , but it gets the level from the channel's buffer instead of decoding data from the channel, which means that the mixer doesn't miss out on any data. + In order to do this, the source channel must have buffering enabled, via the BASS_MIXER_BUFFER flag. + If the mixer is a decoding channel, then the channel's most recent data will be used to get the level. Otherwise, the level will be in sync with what is currently being heard from the mixer, unless the buffer is too small so that the currently heard data isn't in it. + The BASS_CONFIG_MIXER_BUFFER config option can be used to set the buffer size. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_DATA_AVAILABLEQuery the amount of data the channel has buffered. This flag is primarily of use when recording, and can't be used with decoding channels as they do not have playback buffers. buffer can be when using this flag. + + + + + Get the left and right levels of a stereo channel: + + float[] level = new float[2]; // dealing with stereo + if (BassMix.BASS_Mixer_ChannelGetLevel(channel, level)) + { + float left = level[0]; // the left level + float right = level[1]; // the right level + } + + + Dim level(2) As Single ' dealing with stereo + If BassMix.BASS_Mixer_ChannelGetLevel(channel, level) Then + Dim left As Single = level(0) ' the left level + Dim right As Single = level(1) ' the right level + End If + + + + + + Modifies and/or retrieves a channel's mixer flags. + + The handle of the mixer source channel to modify (which was add via or or ) beforehand). + Any combination of these flags (see ): + + BASS_MIXER_BUFFERBuffer the sample data, for use by and . + BASS_MIXER_NORAMPINDon't ramp-in the start, including after seeking (). This is useful for gap-less playback, where a source channel is intended to seamlessly follow another. This does not affect volume and pan changes, which are always ramped. + BASS_MIXER_PAUSEDon't process the source channel (paused mode). + BASS_STREAM_AUTOFREEAutomatically free the source channel when it ends. This allows you to add a channel to a mixer and forget about it, as it will automatically be freed when it has reached the end, or when the source is removed from the mixer or when the mixer is freed. + BASS_SPEAKER_xxxSpeaker assignment flags. + + + The flags (as above) to modify. Flags that are not included in this are left as they are, so it can be set to 0 () in order to just retrieve the current flags. + To modify the speaker flags, any of the BASS_SPEAKER_xxx flags can be used in the mask (no need to include all of them). + If successful, the channel's updated flags are returned, else -1 is returned. Use to get the error code. + This function only deals with the channel's mixer related flags. The channel's standard flags, for example looping (BASS_SAMPLE_LOOP), are unaffected - use to modify them. + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe channel is not plugged into a mixer. + BASS_ERROR_SPEAKERThe mixer does not support the requested speaker(s), or the channel has matrix mixing enabled. + + + + + + // Disable ramping-in of a channel: + BassMix.BASS_Mixer_ChannelFlags(channel, BASSFlag.BASS_MIXER_NORAMPIN, BASSFlag.BASS_MIXER_NORAMPIN); + + // Enable ramping-in of a channel: + BassMix.BASS_Mixer_ChannelFlags(channel, BASSFlag.BASS_DEFAULT, BASSFlag.BASS_MIXER_NORAMPIN); + + + ' Disable ramping-in of a channel: + BassMix.BASS_Mixer_ChannelFlags(channel, BASSFlag.BASS_MIXER_NORAMPIN, BASSFlag.BASS_MIXER_NORAMPIN) + + ' Enable ramping-in of a channel: + BassMix.BASS_Mixer_ChannelFlags(channel, BASSFlag.BASS_DEFAULT, BASSFlag.BASS_MIXER_NORAMPIN) + + + + + + Pauses a mixer source channel (don't process the source). + + The handle of the mixer source channel to pause (which was add via or or ) beforehand). + If successful, then is returned, else is returned. Use to get the error code. + Use this method to pause a mixer source channel currently playing (which stops the mixer from processing that source). + Use to resume a paused mixer source channel. + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe channel is not plugged into a mixer. + BASS_ERROR_SPEAKERThe mixer does not support the requested speaker(s), or the channel has matrix mixing enabled. + + + + + + + Starts (or resumes) playback of a mixer source channel (process the source). + + The handle of the mixer source channel to play (which was add via or or ) beforehand). + If successful, then is returned, else is returned. Use to get the error code. + If the mixer source channel is already playing this method has no effect - else it removes the flag from the mixer source channel. + Use to pause a mixer source channel. + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe channel is not plugged into a mixer. + BASS_ERROR_SPEAKERThe mixer does not support the requested speaker(s), or the channel has matrix mixing enabled. + + + + + + + Checks if a mixer source channel is active (playing) or paused. + + The handle of the mixer source channel to check (which was add via or or ) beforehand). + The return value is one of the folowing (see ): + + BASS_ACTIVE_STOPPEDThe source is not active, or handle is not a valid mixer source channel. + BASS_ACTIVE_PLAYINGThe source is playing. + BASS_ACTIVE_PAUSEDThe source is paused. + + + + BASS_ACTIVE_STOPPED will not automatically be returned once the end of the source mixer channel has been reached (unless you have specified with the or or method). + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe channel is not plugged into a mixer. + BASS_ERROR_SPEAKERThe mixer does not support the requested speaker(s), or the channel has matrix mixing enabled. + + + + + + + Unplugs a channel from a mixer. + + The handle of the mixer source channel to unplug (which was add via or ) beforehand). + If successful, then is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe channel is not plugged into a mixer. + + + + + + + Retrieves the mixer that a channel is plugged into. + + The mixer source channel handle (which was add via or beforehand). + If successful, the mixer stream's handle is returned, else 0 is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe channel is not plugged into a mixer. + + + + + + + Sets the playback position of a mixer source channel. + + The mixer source channel handle (which was add via or ) beforehand). + The position, in bytes. With MOD musics, the (order,row) method can be used to set the position in orders and rows instead of bytes. + + + BASS_POS_BYTEThe position is in bytes, which will be rounded down to the nearest sample boundary. + BASS_POS_MUSIC_ORDERThe position is in orders and rows... use . (HMUSIC only). + BASS_MUSIC_POSRESETFlag: Stop all notes. This flag is applied automatically if it has been set on the channel, eg. via . (HMUSIC). + BASS_MUSIC_POSRESETEXFlag: Stop all notes and reset bpm/etc. This flag is applied automatically if it has been set on the channel, eg. via . (HMUSIC). + BASS_MIXER_NORAMPINFlag: Don't ramp-in the start after seeking. This flag is applied automatically if it has been set on the channel, eg. via . (HMUSIC). + + Other modes and flags may be supported by add-ons, see the documentation. + + If successful, then is returned, else is returned. Use to get the error code. + This function works exactly like the standard , except that it also resets things for the channel in the mixer, + well as supporting the BASS_MIXER_NORAMPIN flag. See for details. + For custom looping purposes (eg. in a mixtime SYNCPROC), the standard function should be used instead of this + The playback buffer of the mixer can be flushed by using pos = 0. + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe channel is not plugged into a mixer. + BASS_ERROR_NOTFILEThe stream is not a file stream. + BASS_ERROR_POSITIONThe requested position is illegal. + BASS_ERROR_NOTAVAILThe download has not yet reached the requested position. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Sets the position of a source stream to 35seconds: + + BassMix.BASS_Mixer_ChannelSetPosition(streamA, Bass.BASS_ChannelSeconds2Bytes(streamA, 35.0)); + + + BassMix.BASS_Mixer_ChannelSetPosition(streamA, Bass.BASS_ChannelSeconds2Bytes(streamA, 35.0)); + + Reset the playback buffer of the mixer: + + BassMix.BASS_Mixer_ChannelSetPosition(mixer, 0L); + + + BassMix.BASS_Mixer_ChannelSetPosition(mixer, 0L) + + + + + + Sets the playback position in bytes of a mixer source channel. + + The mixer source channel handle (which was add via or ) beforehand). + The position, in bytes. With MOD musics, the (order,row) method can be used to set the position in orders and rows instead of bytes. + The playback buffer of the mixer can be flushed by using pos = 0. + + If successful, then is returned, else is returned. Use to get the error code. + This function works exactly like the standard , except that it also resets things for the channel in the mixer, + well as supporting the BASS_MIXER_NORAMPIN flag. See for details. + For custom looping purposes (eg. in a mixtime SYNCPROC), the standard function should be used instead of this + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe channel is not plugged into a mixer. + BASS_ERROR_NOTFILEThe stream is not a file stream. + BASS_ERROR_POSITIONThe requested position is illegal. + BASS_ERROR_NOTAVAILThe download has not yet reached the requested position. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Sets the position of a source stream to 35seconds: + + BassMix.BASS_Mixer_ChannelSetPosition(streamA, Bass.BASS_ChannelSeconds2Bytes(streamA, 35.0)); + + + BassMix.BASS_Mixer_ChannelSetPosition(streamA, Bass.BASS_ChannelSeconds2Bytes(streamA, 35.0)); + + Reset the playback buffer of the mixer: + + BassMix.BASS_Mixer_ChannelSetPosition(mixer, 0L); + + + BassMix.BASS_Mixer_ChannelSetPosition(mixer, 0L) + + + + + + Retrieves the playback position of a mixer source channel. + + The mixer source channel handle (which was add via or ) beforehand). + + + BASS_POS_BYTEGet the position in bytes. + BASS_POS_MUSIC_ORDERGet the position in orders and rows... LoWord = order, HiWord = row * scaler (). (HMUSIC only). + + Other modes and flags may be supported by add-ons, see the documentation. + + If an error occurs, -1 is returned, use to get the error code. + If successful, the position is returned. + + This function is like the standard , but it compensates for the mixer's buffering to return the source channel position that is currently being heard. + So when used with a decoding channel (eg. a mixer source channel), this method will return the current decoding position. + But if the mixer output is being played, then there is a playback buffer involved. This function compensates for that, to return the position that is currently being heard. + If the mixer itself is a decoding channel, then this function is identical to using . + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not plugged into a mixer. + BASS_ERROR_NOTAVAILThe requested position is not available. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Retrieves the playback position of a mixer source channel, optionally accounting for some latency. + + The mixer source channel handle (which was add via or ) beforehand). + How to retrieve the position. One of the following: + + BASS_POS_BYTEGet the position in bytes. + BASS_POS_MUSIC_ORDERGet the position in orders and rows... LoWord = order, HiWord = row * scaler (). (HMUSIC only). + + Other modes and flags may be supported by add-ons, see the documentation. + + How far back (in bytes) in the mixer output to get the source channel's position from. + If an error occurs, -1 is returned, use to get the error code. + If successful, the channel's position is returned. + + compensates for the mixer's playback buffering to give the position that is currently being heard, but if the mixer is feeding some other output system, it will not know how to compensate for that. + This function fills that gap by allowing the latency to be specified in the call. This functionality requires the mixer to keep a record of its sources' position going back some time, and that is enabled via the flag when a mixer is created, with the config option determining how far back the position record goes. + If the mixer is not a decoding channel (not using the flag), then it will automatically have a position record at least equal to its playback buffer length. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not plugged into a mixer. + BASS_ERROR_NOTAVAILThe requested position mode is not available, or delay goes beyond where the mixer has record of the source channel's position. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Retrieves the playback position in bytes of a mixer source channel. + + The mixer source channel handle (which was add via or ) beforehand). + If an error occurs, -1 is returned, use to get the error code. + If successful, the position is returned. + + This function is like the standard , but it compensates for the mixer's buffering to return the source channel position that is currently being heard. + So when used with a decoding channel (eg. a mixer source channel), this method will return the current decoding position. + But if the mixer output is being played, then there is a playback buffer involved. This function compensates for that, to return the position that is currently being heard. + If the mixer itself is a decoding channel, then this function is identical to using . + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not plugged into a mixer. + BASS_ERROR_NOTAVAILThe requested position is not available. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Sets a channel's mixing matrix, if it has one. + + The mixer source channel handle (which was add via or ) beforehand). + The 2-dimensional array (float[,]) of the mixing matrix. + If successful, a is returned, else is returned. Use to get the error code. + + Normally when mixing channels, the source channels are sent to the output in the same order - the left input is sent to the left output, and so on. Sometimes something a bit more complex than that is required. For example, if the source has more channels than the output, you may want to "downmix" the source so that all channels are present in the output. Equally, if the source has fewer channels than the output, you may want to "upmix" it so that all output channels have sound. Or you may just want to rearrange the channels. Matrix mixing allows all of these. + A matrix mixer is created on a per-source basis (you can mix'n'match normal and matrix mixing), by using the and/or flag when calling or . + The matrix itself is a 2-dimensional array of floating-point mixing levels, with the source channels on one axis, and the output channels on the other. Some simple examples are shown below. + The Matrix layout: + + HorizontalThe Input channels (e.g. 1,0 = left-on,right-off). + VerticalThe Output channels (e.g. 1,0 = left-on,right-off). + + + ---------> (Input) ---------> (Input) + | L R | L R + | L 1 0 |LF 1 0 + | R 0 1 |RF 0 1 + v |LR 1 0 + (Output) |RR 0 1 + v + (Output) + + + When streaming multi-channel sample data, the channel order of each sample is as follows: + + 3 channelsleft-front, right-front, center. + 4 channelsleft-front, right-front, left-rear/side, right-rear/side. + 6 channels(5.1)left-front, right-front, center, LFE, left-rear/side, right-rear/side. + 8 channels(7.1)left-front, right-front, center, LFE, left-rear/side, right-rear/side, left-rear center, right-rear center. + + When using matrix mixing, the source channel's volume attribute still has effect, but the pan attribute doesn't. Whenever necessary, panning changes can be achieved by modifying the matrix. + Do NOT use .Net jagged arrays, but only two-dimensional C-style arrays - as shown in the examples below! + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not plugged into a mixer. + BASS_ERROR_NOTAVAILThe channel is not using matrix mixing. + + + + + The following example shows how to use Matrix mixing (stereo to quad matrix): + + // the source stream + int streamA = Bass.BASS_StreamCreateFile(_fileName, 0, 0, BASSFlag.BASS_STREAM_DECODE); + // create a 4-channel mixer stream + BASS_CHANNELINFO i = Bass.BASS_ChannelGetInfo(streamA); + int mixer = BassMix.BASS_Mixer_StreamCreate(i.freq, 4, BASSFlag.BASS_DEFAULT ); + // add the source stream to the mixer with the matrix option + BassMix.BASS_Mixer_StreamAddChannel(mixer, streamA, BASSFlag.BASS_MIXER_MATRIX); + // define a mixing matrix for the source stream + float[,] matrix = { // stereo to quad matrix + {1, 0}, // left in = left front out + {0, 1}, // right in = right front out + {1, 0}, // left in = left rear out + {0, 1} // right in = right rear out + }; + // apply the matrix + BassMix.BASS_Mixer_ChannelSetMatrix(streamA, matrix); + // and play it + Bass.BASS_ChannelPlay(mixer, false); + + + ' the source stream + Dim streamA As Integer = Bass.BASS_StreamCreateFile(_fileName, 0, 0, BASSFlag.BASS_STREAM_DECODE) + ' create a 4-channel mixer stream + Dim i As BASS_CHANNELINFO = Bass.BASS_ChannelGetInfo(streamA) + Dim mixer As Integer = BassMix.BASS_Mixer_StreamCreate(i.freq, 4, BASSFlag.BASS_DEFAULT) + ' add the source stream to the mixer with the matrix option + BassMix.BASS_Mixer_StreamAddChannel(mixer, streamA, BASSFlag.BASS_MIXER_MATRIX) + ' define a mixing matrix for the source stream + Dim matrix(,) As Single = { ' stereo to quad matrix + {1, 0}, ' left in = left front out + {0, 1}, ' right in = right front out + {1, 0}, ' left in = left rear out + {0, 1} ' right in = right rear out + } + BassMix.BASS_Mixer_ChannelSetMatrix(streamA, matrix) + ' and play it + Bass.BASS_ChannelPlay(mixer, False) + + Here are some more matrix examples... + + // In = stereo, Out = stereo + float[,] matrix = { + {1, 0}, // left out = left in + {0, 1}, // right out = right in + }; + + // In = stereo, Out = swapped stereo + float[,] matrix = { + {0, 1}, // left out = right in + {1, 0}, // right out = left in + }; + + // In = stereo, Out = mono + float[,] matrix = { + {0.5f, 0.5f} // mono out = half left + right in + }; + + // In = stereo, Out = quadraphonic (4 channels) + float[,] matrix = { // stereo to quad matrix + {1, 0}, // left-front out = left in + {0, 1}, // right-front out = right in + {1, 0}, // left rear out = left in + {0, 1} // right rear out = right in + }; + + // In = mono, Out = quadraphonic (4 channels) + float[,] matrix = { // mono to quad matrix + {1}, // left-front out = mono in + {1}, // right-front out = mono in + {1}, // left rear out = mono in + {1} // right rear out = mono in + }; + + + + + + Retrieves a channel's mixing matrix, if it has one. + + The mixer source channel handle (which was add via or ) beforehand). + The 2-dimentional array (float[,]) where to write the matrix. + If successful, a is returned, else is returned. Use to get the error code. + + For more details see . The array must be big enough to get the matrix. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not plugged into a mixer. + BASS_ERROR_NOTAVAILThe channel is not using matrix mixing. + + + + + Get the matrix of a stereo channel plugged into a quad mixer: + + // you must initialize the array size correctly before getting the matrix! + float[,] matrixGet = new float[4,2]; + BassMix.BASS_Mixer_ChannelGetMatrix(streamA, matrixGet); + + + ' you must initialize the array size correctly before getting the matrix! + Dim matrixGet(4, 2) As Single + BassMix.BASS_Mixer_ChannelGetMatrix(streamA, matrixGet) + + + + + + Retrieves the current position and value of an envelope on a channel. + + The mixer source channel handle (which was add via or ) beforehand). + The envelope to get the position/value of. One of the following (see ): + + BASS_MIXER_ENV_FREQSample rate. + BASS_MIXER_ENV_VOLVolume. + BASS_MIXER_ENV_PANPanning/balance. + + + A reference to a variable to receive the envelope value at the current position. + If successful, the current position of the envelope is returned, else -1 is returned. Use to get the error code. + + The envelope's current position is not necessarily what is currently being heard, due to buffering. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not plugged into a mixer. + BASS_ERROR_ILLTYPE is not valid. + BASS_ERROR_NOTAVAILThere is no envelope of the requested type on the channel. + + + + + + float val = 0f; + int pos = BassMix.BASS_Mixer_ChannelGetEnvelope(source, + BASSMIXEnvelope.BASS_MIXER_ENV_VOL, ref val); + Console.WriteLine("Pos={0}, Val={1}", pos, val); + + + Dim val As Single = 0F + Dim pos As Integer = BassMix.BASS_Mixer_ChannelGetEnvelope(source, + BASSMIXEnvelope.BASS_MIXER_ENV_VOL, val) + Console.WriteLine("Pos={0}, Val={1}", pos, val) + + + + + + Retrieves the current position and value of an envelope on a channel. + + The mixer source channel handle (which was add via or ) beforehand). + The envelope to get the position/value of. One of the following (see ): + + BASS_MIXER_ENV_FREQSample rate. + BASS_MIXER_ENV_VOLVolume. + BASS_MIXER_ENV_PANPanning/balance. + + + A reference to an object to receive the envelope value at the current position ( = don't retrieve it). + If successful, the current position of the envelope is returned, else -1 is returned. Use to get the error code. + + The envelope's current position is not necessarily what is currently being heard, due to buffering. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not plugged into a mixer. + BASS_ERROR_ILLTYPE is not valid. + BASS_ERROR_NOTAVAILThere is no envelope of the requested type on the channel. + + + + + + int pos = BassMix.BASS_Mixer_ChannelGetEnvelope(source, + BASSMIXEnvelope.BASS_MIXER_ENV_VOL, null); + Console.WriteLine("Pos={0}", val); + + + Dim pos As Integer = BassMix.BASS_Mixer_ChannelGetEnvelope(source, + BASSMIXEnvelope.BASS_MIXER_ENV_VOL, Nothing) + Console.WriteLine("Pos={0}", pos) + + + + + + Sets the current position of an envelope on a channel. + + The mixer source channel handle (which was add via or ) beforehand). + The envelope to set the position/value of. One of the following (see ): + + BASS_MIXER_ENV_FREQSample rate. + BASS_MIXER_ENV_VOLVolume. + BASS_MIXER_ENV_PANPanning/balance. + + + The new envelope position, in bytes. If this is beyond the end of the envelope it will be capped or looped, depending on whether the envelope has looping enabled. + If successful, the current position of the envelope is returned, else -1 is returned. Use to get the error code. + + During playback, the effect of changes are not heard instantaneously, due to buffering. To reduce the delay, use the BASS_CONFIG_BUFFER config option config option to reduce the buffer length. + Note: Envelopes deal in mixer positions, not sources! + So when you are changing the source position (e.g. via the envelope's positions doesn't change with it. + You might use this method to align the envelope position accorting to the new source position (see example below). + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not plugged into a mixer. + BASS_ERROR_ILLTYPE is not valid. + BASS_ERROR_NOTAVAILThere is no envelope of the requested type on the channel. + + + + + Align the envelope position when seeking on the source: + + // set a volume envelope on a source mixer channel (do this just once) + BASS_MIXER_NODE[] nodes = + { + new BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 3d), 1f), + new BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 5d), 0f), + new BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 7d), 0f), + new BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 9d), 1f) + }; + BassMix.BASS_Mixer_ChannelSetEnvelope(source, BASSMIXEnvelope.BASS_MIXER_ENV_VOL, nodes); + ... + + // change the source position and align the envelope position to it + // pause mixer + Bass.BASS_ChannelLock(mixer, true); + BassMix.BASS_Mixer_ChannelSetPosition(source, newPos); + // convert source pos to mixer pos + long envPos = Bass.BASS_ChannelSeconds2Bytes(mixer, Bass.BASS_ChannelBytes2Seconds(source, newPos)); + BassMix.BASS_Mixer_ChannelSetEnvelopePos(source, BASSMIXEnvelope.BASS_MIXER_ENV_VOL, envPos); + // resume mixer + Bass.BASS_ChannelLock(mixer, false); + ... + + + Dim nodes As BASS_MIXER_NODE() = + { + New BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 3.0), 1F), + New BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 5.0), 0F), + New BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 7.0), 0F), + New BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 9.0), 1F) + } + BassMix.BASS_Mixer_ChannelSetEnvelope(source, BASSMIXEnvelope.BASS_MIXER_ENV_VOL, nodes) + ... + + ' change the source position and align the envelope position to it + ' pause mixer + Bass.BASS_ChannelLock(mixer, True) + BassMix.BASS_Mixer_ChannelSetPosition([source], newPos) + ' convert source pos to mixer pos + Dim envPos As Long = Bass.BASS_ChannelSeconds2Bytes(mixer, Bass.BASS_ChannelBytes2Seconds([source], newPos)) + BassMix.BASS_Mixer_ChannelSetEnvelopePos([source], BASSMIXEnvelope.BASS_MIXER_ENV_VOL, envPos) + ' resume mixer + Bass.BASS_ChannelLock(mixer, False) + ... + + + + + + Sets an envelope to modify the sample rate, volume or pan of a channel over a period of time. + + The mixer source channel handle (which was add via or ) beforehand). + The envelope to get the position/value of. One of the following (see ): + + BASS_MIXER_ENV_FREQSample rate. + BASS_MIXER_ENV_VOLVolume. + BASS_MIXER_ENV_PANPanning/balance. + BASS_MIXER_ENV_LOOPLoop the envelope. This is a flag and can be used in combination with any of the above. + + + The array of envelope nodes, which should have sequential positions. + The number of elements in the nodes array... 0 = no envelope. + If successful, is returned, else is returned. Use to get the error code. + + Envelopes are applied on top of the channel's attributes, as set via . + In the case of BASS_MIXER_ENV_FREQ and BASS_MIXER_ENV_VOL, + the final sample rate and volume is a product of the channel attribute and the envelope. + While in the BASS_MIXER_ENV_PAN case, the final panning is a sum of the channel attribute and envelope. + can be used to get the current envelope position, + and a BASS_SYNC_MIXER_ENVELOPE sync can be set via to be informed of when an envelope ends. + The function can be called again from such a sync, in order to set a new envelope to follow the old one. + Any previous envelope of the same type is replaced by the new envelope. A copy is made of the nodes array, so it does not need to persist beyond this function call. + Note: Envelopes deal in mixer positions, not sources! + You might use to adjust the envelope to a source channel position. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not plugged into a mixer. + BASS_ERROR_ILLTYPE is not valid. + + + + + Set an envelope to bounce the pan position between left and right every 4 seconds: + + BASS_MIXER_NODE[] nodes = + { + new BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 0d), 0f), + new BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 1d), -1f), + new BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 3d), 1f), + new BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 4d), 0f) + }; + BassMix.BASS_Mixer_ChannelSetEnvelope(_channel, BASSMIXEnvelope.BASS_MIXER_ENV_PAN | BASSMIXEnvelope.BASS_MIXER_ENV_LOOP, nodes, 4); + + + Dim nodes As BASS_MIXER_NODE() = + { + New BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 0.0), 0F), + New BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 1.0), -1F), + New BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 3.0), 1F), + New BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 4.0), 0F) + } + BassMix.BASS_Mixer_ChannelSetEnvelope(_channel, BASSMIXEnvelope.BASS_MIXER_ENV_PAN | BASSMIXEnvelope.BASS_MIXER_ENV_LOOP, nodes, 4) + + Remove any still available envelope nodes: + + BassMix.BASS_Mixer_ChannelSetEnvelope(_channel, BASSMIXEnvelope.BASS_MIXER_ENV_PAN, null, 0); + + + BassMix.BASS_Mixer_ChannelSetEnvelope(_channel, BASSMIXEnvelope.BASS_MIXER_ENV_PAN, Nothing, 0) + + + + + + Sets an envelope to modify the sample rate, volume or pan of a channel over a period of time. + + The mixer source channel handle (which was add via or ) beforehand). + The envelope to get the position/value of. One of the following (see ): + + BASS_MIXER_ENV_FREQSample rate. + BASS_MIXER_ENV_VOLVolume. + BASS_MIXER_ENV_PANPanning/balance. + BASS_MIXER_ENV_LOOPLoop the envelope. This is a flag and can be used in combination with any of the above. + + + The array of envelope nodes, which should have sequential positions ( = no envelope). + If successful, is returned, else is returned. Use to get the error code. + + Envelopes are applied on top of the channel's attributes, as set via . + In the case of BASS_MIXER_ENV_FREQ and BASS_MIXER_ENV_VOL, + the final sample rate and volume is a product of the channel attribute and the envelope. + While in the BASS_MIXER_ENV_PAN case, the final panning is a sum of the channel attribute and envelope. + can be used to get the current envelope position, + and a BASS_SYNC_MIXER_ENVELOPE sync can be set via to be informed of when an envelope ends. + The function can be called again from such a sync, in order to set a new envelope to follow the old one. + Any previous envelope of the same type is replaced by the new envelope. A copy is made of the nodes array, so it does not need to persist beyond this function call. + Note: Envelopes deal in mixer positions, not sources! + You might use to adjust the envelope to a source channel position. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not plugged into a mixer. + BASS_ERROR_ILLTYPE is not valid. + + + + + Volume curve envelope starting after 3 seconds, ending after 9 seconds: + + BASS_MIXER_NODE[] nodes = + { + new BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 3d), 1f), + new BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 5d), 0.3f), + new BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 7d), 0.5f), + new BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 9d), 1f) + }; + BassMix.BASS_Mixer_ChannelSetEnvelope(_channel, BASSMIXEnvelope.BASS_MIXER_ENV_VOL, nodes); + + + Dim nodes As BASS_MIXER_NODE() = + { + New BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 3.0), 1F), + New BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 5.0), 0.3F), + New BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 7.0), 0.5F), + New BASS_MIXER_NODE(Bass.BASS_ChannelSeconds2Bytes(_mixer, 9.0), 1F) + } + BassMix.BASS_Mixer_ChannelSetEnvelope(_channel, BASSMIXEnvelope.BASS_MIXER_ENV_VOL, nodes) + + + + + + Sets up a synchronizer on a mixer source channel. + + The mixer source channel handle (which was add via or ) beforehand). + The type of sync (see for details). This can be one of the standard sync types, as available via , or one of the mixer specific sync types listed below plus one of the following flags: + + BASS_SYNC_ONETIMECall the sync only once, and then remove it from the channel. + BASS_SYNC_MIXTIMECall the sync function when the sync occurs during decoding/mixing, instead of delaying the call until the sync is actually heard. This is automatically applied with decoding channels, as they can not be played/heard. + + + The sync parameters, depends on the sync type (see or for details). + The callback function which should be invoked with the sync. + User instance data to pass to the callback function. + If succesful, then the new synchronizer's handle is returned, else 0 is returned. Use to get the error code. + + Sync types, with param and data definitions: + + BASS_SYNC_MIXER_ENVELOPESync when an envelope ends. This is not triggered by looping envelopes. + param : envelope type to sync on, 0 = all types. + data : envelope type. + + BASS_SYNC_MIXER_ENVELOPE_NODESync when an envelope reaches a new node. + param : envelope type to sync on, 0 = all types. data : LOWORD = envelope type, HIWORD = node number. + data : LOWORD = envelope type, HIWORD = node number. + + BASS_SYNC_STALLThis is like the standard BASS_SYNC_STALL sync, except it can be either mixtime or not. + param : not used. + data : 0 = stalled, 1 = resumed. + + + When used on a decoding channel (eg. a mixer source channel), syncs set with are automatically "mixtime", + which means that they will be triggered as soon as the sync event is encountered during decoding. + But if the mixer output is being played, then there is a playback buffer involved, which will delay the hearing of the sync event. + This function compensates for that, delaying the triggering of the sync until the event is actually heard. + If the mixer itself is a decoding channel, or the BASS_SYNC_MIXTIME flag is used, then there is effectively no real difference between this function and . + One sync type that is slightly different is the BASS_SYNC_STALL sync, which can be either mixtime or not. + Sync types that would automatically be mixtime when using are not so when using this function. + The BASS_SYNC_MIXTIME flag should be specified in those cases, or used instead. + If the mixer itself is a decoding channel, or the BASS_SYNC_MIXTIME flag is used, then there is effectively no real difference between this function and BASS_ChannelSetSync, except for the mixer specific sync types listed above. + When a source is removed from a mixer, any syncs that have been set on it via this function are automatically removed. + If the channel is subsequently plugged back into a mixer, the previous syncs will not still be set on it. Syncs set via are unaffected. + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe channel is not plugged into a mixer. + BASS_ERROR_ILLTYPEAn illegal was specified. + BASS_ERROR_ILLPARAMAn illegal was specified. + + + + See for an example on how to use synchronizers. + + + + + + + + + + + + + + + Sets up an extended synchronizer on a mixer source channel. + + The mixer source channel handle (which was add via or ) beforehand). + The type of sync (see for details). This can be one of the standard sync types, as available via , or one of the mixer specific sync types listed below plus one of the following flags: + + BASS_SYNC_ONETIMECall the sync only once, and then remove it from the channel. + BASS_SYNC_MIXTIMECall the sync function when the sync occurs during decoding/mixing, instead of delaying the call until the sync is actually heard. This is automatically applied with decoding channels, as they can not be played/heard. + + + The sync parameters, depends on the sync type (see or for details). + The callback function which should be invoked with the sync. + User instance data to pass to the callback function. + If succesful, then the new synchronizer's handle is returned, else 0 is returned. Use to get the error code. + + Sync types, with param and data definitions: + + BASS_SYNC_MIXER_ENVELOPESync when an envelope ends. This is not triggered by looping envelopes. + param : envelope type to sync on, 0 = all types. + data : envelope type. + + BASS_SYNC_MIXER_ENVELOPE_NODESync when an envelope reaches a new node. + param : envelope type to sync on, 0 = all types. data : LOWORD = envelope type, HIWORD = node number. + data : LOWORD = envelope type, HIWORD = node number. + + BASS_SYNC_STALLThis is like the standard BASS_SYNC_STALL sync, except it can be either mixtime or not. + param : not used. + data : 0 = stalled, 1 = resumed. + + + The main difference between this method and is, that this method invokes the callback. + This callback contains an extra 'offeset' parameter, which defines the position of the sync occurrence within the current update cycle of the source converted to the mixer stream position. + This offset might be used to calculate more accurate non-mixtime sync triggers (as with non-mixtime sync's a variable delay is to be expected, as the accuracy depends on the sync thread waking in time, and there is no guarantee when that will happen) - + as well as mixtime syncs are only accurate to the current update period, as they are triggered within such. + So a mixtime sync is being triggered ahead of the actual mixer position being heard. The 'offset' parameter might be used to compensate for that. + When used on a decoding channel (eg. a mixer source channel), syncs set with are automatically "mixtime", + which means that they will be triggered as soon as the sync event is encountered during decoding. + But if the mixer output is being played, then there is a playback buffer involved, which will delay the hearing of the sync event. + This function compensates for that, delaying the triggering of the sync until the event is actually heard. + If the mixer itself is a decoding channel, or the BASS_SYNC_MIXTIME flag is used, then there is effectively no real difference between this function and . + One sync type that is slightly different is the BASS_SYNC_STALL sync, which can be either mixtime or not. + Sync types that would automatically be mixtime when using are not so when using this function. + The BASS_SYNC_MIXTIME flag should be specified in those cases, or used instead. + If the mixer itself is a decoding channel, or the BASS_SYNC_MIXTIME flag is used, then there is effectively no real difference between this function and BASS_ChannelSetSync, except for the mixer specific sync types listed above. + When a source is removed from a mixer, any syncs that have been set on it via this function are automatically removed. + If the channel is subsequently plugged back into a mixer, the previous syncs will not still be set on it. Syncs set via are unaffected. + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe channel is not plugged into a mixer. + BASS_ERROR_ILLTYPEAn illegal was specified. + BASS_ERROR_ILLPARAMAn illegal was specified. + + + + See for an example on how to use the extended synchronizer. + + + + Removes a synchronizer from a mixer source channel. + + The mixer source channel handle (as returned by or ). + Handle of the synchronizer to remove (return value of a previous call). + If succesful, is returned, else is returned. Use to get the error code. + This function can only remove syncs that were set via , not those that were set via . + + + ERROR CODEDescription + BASS_ERROR_HANDLEAt least one of and is not valid. + + + + + + + Creates a splitter stream (adds a reader channel to a decoding source channel). + + The handle of the decoding source channel to split... a HMUSIC, HSTREAM or HRECORD (e.g. created with ). + The channel falgs to be used to create the reader channel, any combination of these flags (see ): + + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D streams must be mono. The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_AUTOFREEAutomatically free the stream when it ends. This allows you to stream a file and forget about it, as BASS will automatically free the stream's resources when it has reached the end or when (or ) is called. + BASS_STREAM_DECODESplit the sample data, without playing it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPLIT_SLAVEOnly get data from the splitter buffer, not directly from the source. + BASS_SPEAKER_xxxSpeaker assignment flags. These flags have no effect when the stream is more than stereo. + + + The target (readers) channel mapping definition, which is an array of source channel index values (0=1st channel, 1=2nd channel, 2=3rd channel, 3=4th channel etc.) ending with a final -1 element (use to create a 1:1 reader). + If successful, the new reader stream's handle is returned, else 0 is returned. Use to get the error code. + + A "splitter" basically does the opposite of a mixer: it splits a single source into multiple streams rather then mixing multiple sources into a single stream. Like mixer sources, splitter sources must be decoding channels. + The splitter stream will have the same sample rate and resolution as its source, but it can have a different number of channels, as dictated by the mapping parameter. + Even when the number of channels is different (and so the amount of data produced is different), will give the source length, and will give the source position that is currently being output by the splitter stream. + All splitter streams with the same source share a buffer to access its sample data. + The length of the buffer is determined by the BASS_CONFIG_SPLIT_BUFFER config option; the splitter streams should not be allowed to drift apart beyond that, otherwise those left behind will suffer buffer overflows. + A splitter stream's buffer state can be reset via ; that can also be used to reset a splitter stream that has ended, so that it can be played again. + If the BASS_SPLIT_SLAVE flag is used, the splitter stream will only receive data from the buffer and will not request more data from the source, so it can only receive data that has already been received by another splitter stream with the same source. The BASS_SPLIT_SLAVE flag can be toggled at any time via . + When is used on a splitter stream, its source will be set to the requested position and the splitter stream's buffer state will be reset so that it immediately receives data from the new position. + The position change will affect all of the source's splitter streams, but the others will not have their buffer state reset; they will continue to receive any buffered data before reaching the data from the new position. + can be used to reset the buffer state. + Use with a splitter channel to remove it from the source. + When a source is freed, all of its splitter streams are automatically freed. + The array defines the channel number to be created for the reader as well as which source channels should be used for each. + This enables you to create a reader stream which extract certain source channels (e.g. create a mono reader based on a stereo source), remaps the channel order (e.g. swap left and right in the reader) or even contains more channels than the source (e.g. create a 5.1 reader based on a stereo source). + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_HANDLEThe is not valid. + BASS_ERROR_DECODEThe is not a decoding channel. + BASS_ERROR_ILLPARAMThe contains an invalid channel index. + BASS_ERROR_NOTAVAILOnly decoding streams (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported (ie. no WDM drivers). + BASS_ERROR_SPEAKERThe device/drivers do not support the requested speaker(s), or you're attempting to assign a stereo stream to a mono speaker. + BASS_ERROR_MEMThere is insufficent memory. + BASS_ERROR_NO3DCouldn't initialize 3D support for the stream. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + Away from Windows, all mixing is done in software (by BASS), so the BASS_SAMPLE_SOFTWARE flag is unnecessary. The BASS_SAMPLE_FX flag is also ignored. + + + Create two 1:1 clones: + + int source = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE); + int reader1 = BassMix.BASS_Split_StreamCreate(source, BASSFlag.BASS_SAMPLE_FLOAT, null); + int reader2 = BassMix.BASS_Split_StreamCreate(source, BASSFlag.BASS_SAMPLE_FLOAT, null); + ... + + + Dim source As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE) + Dim reader1 As Integer = BassMix.BASS_Split_StreamCreate(source, BASSFlag.BASS_SAMPLE_FLOAT, Nothing) + Dim reader2 As Integer = BassMix.BASS_Split_StreamCreate(source, BASSFlag.BASS_SAMPLE_FLOAT, Nothing) + ... + + Here are some more channel mapping examples... + + // create a mono reader containing only the right channel based on a stereo source + int[] mapping = {1,-1}; + + // create a stereo reader which swaps the left and right channel of the stereo source + int[] mapping = {1,0,-1}; + + // create a quad-channel reader based on a stereo source + int[] mapping = {0,1,0,1,-1}; + + // create a sterao reader based on a mono source + int[] mapping = {0,0,-1}; + + + + + + Retrieves the source of a splitter stream. + + The splitter stream handle (which was add via beforehand). + If successful, the source stream's handle is returned, else 0 is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe is not a splitter stream. + + + + + + + Resets a splitter stream or all splitter streams of a source. + + The splitter (as obtained by ) or the source channel handle. + If successful, is returned, else is returned. Use to get the error code. + This function resets the splitter stream's buffer state, so that the next sample data it receives will be from the source's current position. + If the stream has ended, that is reset too, so that it can be played again. Unless called from within a mixtime sync callback, the stream's output buffer (if it has one) is also flushed. + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe is neither a splitter stream or source. + + + + + + + Resets a splitter stream and sets its position in the source buffer. + + The splitter (as obtained by ) or the source channel handle. + How far back (in bytes) to position the splitter in the source buffer. This is based on the source's sample format, which may have a different channel count to the splitter. + If successful, is returned, else is returned. Use to get the error code. + This function is the same as except that it also provides the ability to position the splitter stream within the buffer that is shared by all of the splitter streams of the same source. + A splitter stream's buffer position determines what data it will next receive. For example, if its position is half a second back, it will receive half a second of buffered data before receiving new data from the source. + Calling this function with offset = 0 will result in the next data that the splitter stream receives being new data from the source, and is identical to using . + is automatically limited to the amount of data that the source buffer contains, which is in turn limited to the buffer size, determined by the config option. + The amount of source data buffered, as well as a splitter stream's position within it, is available from . + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe is neither a splitter stream or source. + + + + + + + + + + + + + + + + Retrieves the channel's splitters. + + The handle to check. + The array of splitter handles ( on error, use to get the error code). + + + + Retrieves the amount of buffered data available to a splitter stream, or the amount of data in a splitter source buffer. + + The splitter (as obtained by ) or the source channel handle. + If successful, then the amount of buffered data (in bytes) is returned, else -1 is returned. Use to get the error code. + + With a splitter source, this function reports how much data is in the buffer that is shared by all of its splitter streams. With a splitter stream, this function reports how much data is ahead of it in the buffer, before it will receive any new data from the source. + A splitter stream can be repositioned within the buffer via the function. + The amount of data that can be buffered is limited by the buffer size, which is determined by the config option. + The returned buffered byte count is always based on the source's sample format, even with splitter streams that were created with a different channel count. + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe is neither a splitter stream or source. + + + + + Create two 1:1 clones: + + // create a new splitter + int newsplit = BassMix.BASS_Split_StreamCreate(source, ...); + // get the amount of data an existing splitter has buffered + int offset = BassMix.BASS_Split_StreamGetAvailable(oldsplit); + // add the amount in its playback buffer + offset += BASS_ChannelGetData(oldsplit, null, BASSData.BASS_DATA_AVAILABLE); + // reset the new splitter to that far back in the source buffer + BassMix.BASS_Split_StreamResetEx(newsplit, offset); + // start playing it + Bass.BASS_ChannelPlay(newsplit, false); + + + ' create a new splitter + Dim newsplit As Integer = BassMix.BASS_Split_StreamCreate(source, 0) + ' get the amount of data an existing splitter has buffered + Dim offset As Integer = BassMix.BASS_Split_StreamGetAvailable(oldsplit) + ' add the amount in its playback buffer + offset += BASS_ChannelGetData(oldsplit, Nothing, BASSData.BASS_DATA_AVAILABLE) + ' reset the new splitter to that far back in the source buffer + BassMix.BASS_Split_StreamResetEx(newsplit, offset) + ' start playing it + Bass.BASS_ChannelPlay(newsplit, False) + + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + Load BASS and BASSmix from the application's startup path: + + Bass.LoadMe(); + BassMix.LoadMe(); + ... + // when not used anymore... + BassMix.FreeMe(); + Bass.FreeMe(); + + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + Load BASS and BASSmix from a different directory: + + Bass.LoadMe( @"C:\Development\BASS\_libs" ); + BassMix.LoadMe( @"C:\Development\BASS\_libs" ); + ... + // when not used anymore... + BassMix.FreeMe(); + Bass.FreeMe(); + + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + Mixer envelope attribute types, used with , and to set/retrieve an envelope on a mixer source channel. + + + + + Sample rate. + Envelopes are applied on top of the channel's attributes, as set via . + The final sample rate is the product of the channel attribute and the envelope. + + + + + Volume. + Envelopes are applied on top of the channel's attributes, as set via . + The final volume is the product of the channel attribute and the envelope. + + + + + Panning/Balance. + Envelopes are applied on top of the channel's attributes, as set via . + The final panning is a sum of the channel attribute and envelope. + + + + + Loop the envelope (flag). + + + + + Used with to set an envelope on a mixer source channel. + + + Envelopes are applied on top of the channel's attributes, as set via . + In the case of BASS_MIXER_ENV_FREQ and BASS_MIXER_ENV_VOL, + the final sample rate and volume is a product of the channel attribute and the envelope. + While in the BASS_MIXER_ENV_PAN case, the final panning is a sum of the channel attribute and envelope. + + + + + The postion of the node in bytes. This is based on the mixer's sample format, not the source channel's format! + + Note: Envelopes deal with mixer positions, not sources! + + + + The envelope value at the position. + + + + + Constructor to initialize the members. + + The postion of the node in bytes. This is based on the mixer's sample format, not the source channel's format. + The envelope value at the position. + + + + A description of the mixer envelope node (position, value). + + A description of the mixer envelope node (position, value). + + + + User defined extended mixer synchronizer callback function (see for details). + + The sync handle that has occured (as returned by ). + The channel that the sync occured on (the mixer source channel). + Additional data associated with the sync's occurance. + The user instance data given when was called. + The offset in bytes containing the position of the sync occurrence within the update cycle converted to the mixer stream. + + A sync callback function should be very quick as other syncs can't be processed until it has finished. Attribute slides () are also performed by the sync thread, so are also affected if a sync callback takes a long time. + If the sync is a "mixtime" sync (BASS_SYNC_MIXTIME), then depending on the sync type, the callback will be executed in the update thread. + The specifies the position of the sync within the update buffer converted to the mixer stream position. + Note that the is based on the mixer's sample format, so you'll need to convert that to the source's format if using the sync to trigger things on the source. + The usual restrictions on which BASS functions can be called that apply to stream callbacks () also apply here. + It is also unsafe to call on the same channel from a mixtime sync callback. can be used in a mixtime sync to implement custom looping, eg. set a BASS_SYNC_POS sync at the loop end position and seek to the loop start position in the callback. + + + + + BASS .NET API wrapper for BASSMIDI. + Requires: bassmidi.dll - BASSMIDI Add-On - available @ www.un4seen.com. + + + BASSMIDI is an extension to the BASS audio library, enabling the playing of MIDI files (Musical Instrument Digital Interface), using SF2 soundfonts to provide the sounds. + The MIDI format is used in very much the same way as any of the built-in BASS stream formats - simply call the MIDI stream creation function instead of the BASS built-in functions. + The BASS plugin system (see BASS_PluginLoad) is also supported. + SF2 soundfonts are used to provide the sounds. There are several soundfonts available on the internet. + One example (Chorium) is available from the BASS webpage. On Win32, the Creative 4MB/2MB soundfont (CT4MGM.SF2/CT2MGM.SF2) will be used by default when it's present (in the Windows system directory). + + + + + NOT used - all members are static! + + + + + Creates a sample stream to render real-time MIDI events. + + The number of MIDI channels: 1 (min) - 128 (max). + Any combination of these flags (see ): + + BASS_SAMPLE_8BITSUse 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the sample data will be 16-bit. + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_MONODecode/play the stream (MP3/MP2/MP1 only) in mono, reducing the CPU usage (if it was originally stereo). This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D streams must be mono. The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_LOOPLoop the file. This flag can be toggled at any time using . This flag is ignored when streaming in blocks (BASS_STREAM_BLOCK). + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_AUTOFREEAutomatically free the stream when it ends. This allows you to stream a file and forget about it, as BASS will automatically free the stream's resources when it has reached the end or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + BASS_MIDI_NOFXDisable reverb and chorus processing, saving some CPU time. This flag can be toggled at any time using . + + + Sample rate (in Hz) to render/play the MIDI at (0 = the rate specified in the call). + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + This function creates a stream solely for real-time MIDI events. As it's not based on any file, the stream has no predetermined length and is never-ending. Seeking isn't possible, but it is possible to reset everything, including playback buffer, + by calling (restart = ) or (pos = 0). + MIDI events are applied using the function. If the stream is being played (it's not a decoding channel), then there will be some delay in the effect of the events being heard. + This latency can be reduced by making use of the and options. + Unlike MIDI files, streams created for rendering real-time events are not limited to 16 channels. By default, all the MIDI channels are melodic, but they can be switched to percussion/drums using and the MIDI_EVENT_DRUMS event. + Soundfonts provide the sounds that are used to render a MIDI stream. A default soundfont configuration is applied initially to the new MIDI stream, which can subsequently be overriden using . + To play a MIDI file, use . + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_ILLPARAM is not valid. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + + + + + + + + + + + + + Creates a sample stream from a MIDI sound file. + This overload implements Unicode filenames. The BASS_UNICODE flag will be added automatically. + + Filename for which a stream should be created. + File offset to begin streaming from. + Data length... 0 = use all data up to the end of the file. + Any combination of these flags (see ): + + BASS_SAMPLE_8BITSUse 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the sample data will be 16-bit. + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_MONODecode/play the stream (MP3/MP2/MP1 only) in mono, reducing the CPU usage (if it was originally stereo). This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D streams must be mono. The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_LOOPLoop the file. This flag can be toggled at any time using . This flag is ignored when streaming in blocks (BASS_STREAM_BLOCK). + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_AUTOFREEAutomatically free the stream when it ends. This allows you to stream a file and forget about it, as BASS will automatically free the stream's resources when it has reached the end or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + BASS_MIDI_DECAYENDLet the ending decay naturally (including reverb), instead of stopping abruptly at the end of the file. This doesn't apply when looping. This flag can be toggled at any time using . + BASS_MIDI_NOFXDisable reverb and chorus processing, saving some CPU time. This flag can be toggled at any time using . + + + Sample rate to render/play the MIDI at (0 = the rate specified in the call). + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + BASSMIDI supports format 0/1/2 MIDI files. In the case of format 2, the tracks are rendered/played one after another. RIFF MIDI (RMID) files are also supported. The General MIDI standard events are supported, as are several Roland GS and Yamaha XG NRPN and SysEx events. A full list of supported MIDI events can be found in the documentation. + Soundfonts provide the sounds that are used to render a MIDI stream. A default soundfont configuration is applied initially to the new MIDI stream, which can subsequently be overriden using . + By default, with the BASS_CONFIG_MIDI_AUTOFONT config option enabled, BASSMIDI will also look for a soundfont of the same name as the MIDI file. For example, if the MIDI is "afile.mid", then it will look for a "afile.sf2" (or "afile.mid.sf2"). Note that a MIDI stream can have multiple soundfonts stacked, each providing different presets, for example. + As well as the standard byte/time-based positioning, MIDI tick-based positioning is also supported. The BASS_POS_MIDI_TICK "mode" can be used with , and to deal in ticks. + Marker, cue and lyric events can be retrieved via the function. Syncs (BASS_SYNC_MIDI_MARKER, BASS_SYNC_MIDI_CUE, BASS_SYNC_MIDI_LYRIC, BASS_SYNC_MIDI_EVENT, BASS_SYNC_MIDI_TICK) + can also be used to be notified of their occurrence. + The texts of each track in the MIDI file are available via the + track tag, where track=0 is the first track. A pointer to a series of null-terminated strings is given, the final string ending with a double null. + The first text in the first track is generally the title of the MIDI file. RIFF MIDI tags are also available via the standard tag. + In addition you might also use the method to retrieve the track text. + Unlike with most stream formats, the entire MIDI file is loaded to memory. This means the file can be deleted or moved after calling this function. + As well as providing dedicated stream creation functions, BASSMIDI supports the BASS plugin system, adding MIDI file support to the standard BASS stream creation functions - , , . + This is enabled using the BASS_PluginLoad function. + MIDI streams created via the plugin system use the sample rate specified in the call. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_ILLPARAM is not a valid URL. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + + + + + + + + + + + + + Creates a sample stream from a MIDI memory IntPtr. + This overload implements Unicode filenames. The BASS_UNICODE flag will be added automatically. + + An unmanaged pointer to the memory location as an IntPtr. + File offset to begin streaming from. + Data length... 0 = use all data up to the end of the file. + Any combination of these flags (see ): + + BASS_SAMPLE_8BITSUse 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the sample data will be 16-bit. + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_MONODecode/play the stream (MP3/MP2/MP1 only) in mono, reducing the CPU usage (if it was originally stereo). This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D streams must be mono. The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_LOOPLoop the file. This flag can be toggled at any time using . This flag is ignored when streaming in blocks (BASS_STREAM_BLOCK). + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_AUTOFREEAutomatically free the stream when it ends. This allows you to stream a file and forget about it, as BASS will automatically free the stream's resources when it has reached the end or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + BASS_MIDI_DECAYENDLet the ending decay naturally (including reverb), instead of stopping abruptly at the end of the file. This doesn't apply when looping. This flag can be toggled at any time using . + BASS_MIDI_NOFXDisable reverb and chorus processing, saving some CPU time. This flag can be toggled at any time using . + + + Sample rate to render/play the MIDI at (0 = the rate specified in the call). + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + BASSMIDI supports format 0/1/2 MIDI files. In the case of format 2, the tracks are rendered/played one after another. RIFF MIDI (RMID) files are also supported. The General MIDI standard events are supported, as are several Roland GS and Yamaha XG NRPN and SysEx events. A full list of supported MIDI events can be found in the documentation. + Soundfonts provide the sounds that are used to render a MIDI stream. A default soundfont configuration is applied initially to the new MIDI stream, which can subsequently be overriden using . + By default, with the BASS_CONFIG_MIDI_AUTOFONT config option enabled, BASSMIDI will also look for a soundfont of the same name as the MIDI file. For example, if the MIDI is "afile.mid", then it will look for a "afile.sf2" (or "afile.mid.sf2"). Note that a MIDI stream can have multiple soundfonts stacked, each providing different presets, for example. + As well as the standard byte/time-based positioning, MIDI tick-based positioning is also supported. The BASS_POS_MIDI_TICK "mode" can be used with , and to deal in ticks. + Marker, cue and lyric events can be retrieved via the function. Syncs (BASS_SYNC_MIDI_MARKER, BASS_SYNC_MIDI_CUE, BASS_SYNC_MIDI_LYRIC, BASS_SYNC_MIDI_EVENT, BASS_SYNC_MIDI_TICK) + can also be used to be notified of their occurrence. + The texts of each track in the MIDI file are available via the + track tag, where track=0 is the first track. A pointer to a series of null-terminated strings is given, the final string ending with a double null. + The first text in the first track is generally the title of the MIDI file. RIFF MIDI tags are also available via the standard tag. + In addition you might also use the method to retrieve the track text. + Unlike with most stream formats, the entire MIDI file is loaded to memory. This means the file can be deleted or moved after calling this function. + As well as providing dedicated stream creation functions, BASSMIDI supports the BASS plugin system, adding MIDI file support to the standard BASS stream creation functions - , , . + This is enabled using the BASS_PluginLoad function. + MIDI streams created via the plugin system use the sample rate specified in the call. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_ILLPARAM is not a valid pointer to a memory location. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + + + + + + + + + + + + + Creates a sample stream from a MIDI memory byte[]. + This overload implements Unicode filenames. The BASS_UNICODE flag will be added automatically. + + A managed memory location as a byte[]. + File offset to begin streaming from. + Data length... 0 = use all data up to the end of the file. + Any combination of these flags (see ): + + BASS_SAMPLE_8BITSUse 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the sample data will be 16-bit. + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_MONODecode/play the stream (MP3/MP2/MP1 only) in mono, reducing the CPU usage (if it was originally stereo). This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D streams must be mono. The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_LOOPLoop the file. This flag can be toggled at any time using . This flag is ignored when streaming in blocks (BASS_STREAM_BLOCK). + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_AUTOFREEAutomatically free the stream when it ends. This allows you to stream a file and forget about it, as BASS will automatically free the stream's resources when it has reached the end or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + BASS_MIDI_DECAYENDLet the ending decay naturally (including reverb), instead of stopping abruptly at the end of the file. This doesn't apply when looping. This flag can be toggled at any time using . + BASS_MIDI_NOFXDisable reverb and chorus processing, saving some CPU time. This flag can be toggled at any time using . + + + Sample rate to render/play the MIDI at (0 = the rate specified in the call). + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + BASSMIDI supports format 0/1/2 MIDI files. In the case of format 2, the tracks are rendered/played one after another. RIFF MIDI (RMID) files are also supported. The General MIDI standard events are supported, as are several Roland GS and Yamaha XG NRPN and SysEx events. A full list of supported MIDI events can be found in the documentation. + Soundfonts provide the sounds that are used to render a MIDI stream. A default soundfont configuration is applied initially to the new MIDI stream, which can subsequently be overriden using . + By default, with the BASS_CONFIG_MIDI_AUTOFONT config option enabled, BASSMIDI will also look for a soundfont of the same name as the MIDI file. For example, if the MIDI is "afile.mid", then it will look for a "afile.sf2" (or "afile.mid.sf2"). Note that a MIDI stream can have multiple soundfonts stacked, each providing different presets, for example. + As well as the standard byte/time-based positioning, MIDI tick-based positioning is also supported. The BASS_POS_MIDI_TICK "mode" can be used with , and to deal in ticks. + Marker, cue and lyric events can be retrieved via the function. Syncs (BASS_SYNC_MIDI_MARKER, BASS_SYNC_MIDI_CUE, BASS_SYNC_MIDI_LYRIC, BASS_SYNC_MIDI_EVENT, BASS_SYNC_MIDI_TICK) + can also be used to be notified of their occurrence. + The texts of each track in the MIDI file are available via the + track tag, where track=0 is the first track. A pointer to a series of null-terminated strings is given, the final string ending with a double null. + The first text in the first track is generally the title of the MIDI file. RIFF MIDI tags are also available via the standard tag. + In addition you might also use the method to retrieve the track text. + Unlike with most stream formats, the entire MIDI file is loaded to memory. This means the file can be deleted or moved after calling this function. + As well as providing dedicated stream creation functions, BASSMIDI supports the BASS plugin system, adding MIDI file support to the standard BASS stream creation functions - , , . + This is enabled using the BASS_PluginLoad function. + MIDI streams created via the plugin system use the sample rate specified in the call. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_ILLPARAM is not a valid memory location. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Creates a sample stream from a MIDI file via a user callback function. + + File system to use, which must be , as the entire MIDI file is preloaded. + Any combination of these flags (see ): + + BASS_SAMPLE_8BITSUse 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the sample data will be 16-bit. + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_MONODecode/play the stream (MP3/MP2/MP1 only) in mono, reducing the CPU usage (if it was originally stereo). This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D streams must be mono. The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_LOOPLoop the file. This flag can be toggled at any time using . This flag is ignored when streaming in blocks (BASS_STREAM_BLOCK). + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_AUTOFREEAutomatically free the stream when it ends. This allows you to stream a file and forget about it, as BASS will automatically free the stream's resources when it has reached the end or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + BASS_MIDI_DECAYENDLet the ending decay naturally (including reverb), instead of stopping abruptly at the end of the file. This doesn't apply when looping. This flag can be toggled at any time using . + BASS_MIDI_NOFXDisable reverb and chorus processing, saving some CPU time. This flag can be toggled at any time using . + + + The user defined file functions (see ). + User instance data to pass to the callback functions. + Sample rate to render/play the MIDI at (0 = the rate specified in the call). + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + As there is no file associated with a user file stream, it's not possible for BASSMIDI to look for a soundfont with the same name as the MIDI file. If there is a matching soundfont, it can be applied using . + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_ILLPARAM is not valid. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported (ie. no WDM drivers). + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + See . + + + + + + + + + + + + + + + + + + + + + + + + + + + + Creates a sample stream from an MIDI file on the internet, optionally receiving the downloaded data in a callback. + + URL of the file to stream. Should begin with "http://" or "ftp://". + File position to start streaming from. This is ignored by some servers, specifically when the file length is unknown. + Any combination of these flags (see ): + + BASS_SAMPLE_8BITSUse 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the sample data will be 16-bit. + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_MONODecode/play the stream (MP3/MP2/MP1 only) in mono, reducing the CPU usage (if it was originally stereo). This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D streams must be mono. The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_LOOPLoop the file. This flag can be toggled at any time using . This flag is ignored when streaming in blocks (BASS_STREAM_BLOCK). + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_STATUSPass status info (HTTP/ICY tags) from the server to the callback during connection. This can be useful to determine the reason for a failure. + BASS_STREAM_AUTOFREEAutomatically free the stream when it ends. This allows you to stream a file and forget about it, as BASS will automatically free the stream's resources when it has reached the end or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + BASS_MIDI_DECAYENDLet the ending decay naturally (including reverb), instead of stopping abruptly at the end of the file. This doesn't apply when looping. This flag can be toggled at any time using . + BASS_MIDI_NOFXDisable reverb and chorus processing, saving some CPU time. This flag can be toggled at any time using . + + + Callback function to receive the file as it is downloaded... = no callback. + User instance data to pass to the callback function. + Sample rate to render/play the MIDI at (0 = the rate specified in the call). + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + The entire MIDI file is preloaded, so the standard BASS_STREAM_BLOCK and BASS_STREAM_RESTRATE flags have no effect here. + Regardless of the setting, a matching soundfont is not looked for when opening a MIDI file from a URL. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_NONETNo internet connection could be opened. Can be caused by a bad proxy setting. + BASS_ERROR_ILLPARAM is not a valid URL. + BASS_ERROR_TIMEOUTThe server did not respond to the request within the timeout period, as set with the BASS_CONFIG_NET_TIMEOUT config option. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Creates a MIDI stream from an array of s. + + The array of s to create the stream from (the array should be terminated with a MIDI_EVENT_END event). + The number of pulses per quarter note (or ticks per beat) value of the MIDI stream to create. + Any combination of these flags (see ): + + BASS_SAMPLE_8BITSUse 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the sample data will be 16-bit. + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_MONODecode/play the stream (MP3/MP2/MP1 only) in mono, reducing the CPU usage (if it was originally stereo). This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D streams must be mono. The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_LOOPLoop the file. This flag can be toggled at any time using . This flag is ignored when streaming in blocks (BASS_STREAM_BLOCK). + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_STATUSPass status info (HTTP/ICY tags) from the server to the callback during connection. This can be useful to determine the reason for a failure. + BASS_STREAM_AUTOFREEAutomatically free the stream when it ends. This allows you to stream a file and forget about it, as BASS will automatically free the stream's resources when it has reached the end or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + BASS_MIDI_DECAYENDLet the ending decay naturally (including reverb), instead of stopping abruptly at the end of the file. This doesn't apply when looping. This flag can be toggled at any time using . + BASS_MIDI_NOFXDisable reverb and chorus processing, saving some CPU time. This flag can be toggled at any time using . + + + Sample rate to render/play the MIDI at (0 = the rate specified in the call). + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + The array should be terminated with a MIDI_EVENT_END event, and a MIDI_EVENT_END_TRACK event can be used to mark the end of a track (the next event will be in a new track). + Only the standard MIDI events can be used (plus the END events) and only on 16 channels; any other events (MIXLEVEL/TRANSPOSE/SYSTEMEX) and channels will be ignored. + TEMPO events should only be used in the first track. The position of the events is always set in ticks (the "pos" BASS_MIDI_EVENT member is ignored) and they must be in chronological order within each track. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_NONETNo internet connection could be opened. Can be caused by a bad proxy setting. + BASS_ERROR_ILLPARAM are not valid. + BASS_ERROR_TIMEOUTThe server did not respond to the request within the timeout period, as set with the BASS_CONFIG_NET_TIMEOUT config option. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + + + + + + + + + + + Retrieves a marker from a MIDI stream. + + The MIDI stream to retrieve the marker from. + The type of marker to retrieve, one of the following (see ): + + BASS_MIDI_MARK_CUECue events (MIDI meta event 07). + BASS_MIDI_MARK_KEYSIGKey signature events (MIDI meta event 89). The marker text is in the form of "a b", where a is the number of sharps (if positive) or flats (if negative), and b signifies major (if 0) or minor (if 1). + BASS_MIDI_MARK_LYRICLyric events (MIDI meta event 05). + BASS_MIDI_MARK_MARKERMarker events (MIDI meta event 06). + BASS_MIDI_MARK_TEXTText events (MIDI meta event 01). + BASS_MIDI_MARK_TIMESIGTime signature events (MIDI meta event 88). The marker text is in the form of "a/b c d", where a is the numerator, b is the denominator, c is the metronome pulse, and d is the number of 32nd notes per MIDI quarter-note. + BASS_MIDI_MARK_TICKFLAG: get position in ticks instead of bytes. + + + The marker to retrieve... 0 = the first. + Instance of the class to receive the marker details. + on success, else is returned. Use to get the error code. + The markers are ordered chronologically. + BASS_SYNC_MIDI_xxx Syncs can be used to be informed of when markers are encountered during playback. + If a lyric marker text begins with a '/' (slash) character, that means a new line should be started. If the text begins with a '\' (backslash) character, the display should be cleared. + Lyrics can sometimes be found in BASS_MIDI_MARK_TEXT instead of BASS_MIDI_MARK_LYRIC markers. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ILLTYPEtype in not valid. + BASS_ERROR_ILLPARAMtype in not valid. + + + + + List a MIDI stream's markers: + + BASS_MIDI_MARK mark = new BASS_MIDI_MARK(); + int idx = 0; + while (BassMidi.BASS_MIDI_StreamGetMark(handle, BASSMIDIMarker.BASS_MIDI_MARK_MARKER, idx, mark)) + { + idx++; + Console.WriteLine("{0}.Marker: {1}", idx, mark); + } + + + Dim mark As New BASS_MIDI_MARK() + Dim idx As Integer = 0 + While BassMidi.BASS_MIDI_StreamGetMark(handle, BASSMIDIMarker.BASS_MIDI_MARK_MARKER, idx, mark) + idx += 1 + Console.WriteLine("{0}.Marker: {1}", idx, mark) + End While + + + + + + Retrieves a marker from a MIDI stream. + + The MIDI stream to retrieve the marker from. + The type of marker to retrieve, one of the following (see ): + + BASS_MIDI_MARK_CUECue events (MIDI meta event 07). + BASS_MIDI_MARK_KEYSIGKey signature events (MIDI meta event 89). The marker text is in the form of "a b", where a is the number of sharps (if positive) or flats (if negative), and b signifies major (if 0) or minor (if 1). + BASS_MIDI_MARK_LYRICLyric events (MIDI meta event 05). + BASS_MIDI_MARK_MARKERMarker events (MIDI meta event 06). + BASS_MIDI_MARK_TEXTText events (MIDI meta event 01). + BASS_MIDI_MARK_TIMESIGTime signature events (MIDI meta event 88). The marker text is in the form of "a/b c d", where a is the numerator, b is the denominator, c is the metronome pulse, and d is the number of 32nd notes per MIDI quarter-note. + BASS_MIDI_MARK_TICKFLAG: get position in ticks instead of bytes. + + + The marker to retrieve... 0 = the first. + On success, an instance of the class is returned, else is returned. Use to get the error code. + The markers are ordered chronologically. + BASS_SYNC_MIDI_xxx Syncs can be used to be informed of when markers are encountered during playback. + If a lyric marker text begins with a '/' (slash) character, that means a new line should be started. If the text begins with a '\' (backslash) character, the display should be cleared. + Lyrics can sometimes be found in BASS_MIDI_MARK_TEXT instead of BASS_MIDI_MARK_LYRIC markers. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ILLTYPEtype in not valid. + BASS_ERROR_ILLPARAMtype in not valid. + + + + + List a MIDI stream's markers: + + int idx = 0; + BASS_MIDI_MARK mark; + while ((mark = BassMidi.BASS_MIDI_StreamGetMark(handle, BASSMIDIMarker.BASS_MIDI_MARK_MARKER, idx)) != null) + { + idx++; + Console.WriteLine("{0}.Marker: {1}", idx, mark); + } + + + Dim idx As Integer = 0 + Dim mark As BASS_MIDI_MARK + While True + mark = BassMidi.BASS_MIDI_StreamGetMark(stream, BASSMIDIMarker.BASS_MIDI_MARK_MARKER, idx) + If mark Is Nothing Then + Exit While + End If + idx += 1 + Console.WriteLine("{0}.Marker: {1}", idx, mark) + End While + + + + + + Applies an event to a MIDI stream. + + The MIDI stream to apply the event to (as returned by ). + The MIDI channel to apply the event in... 0 (channel 1) - 15 (channel 16). + The event to apply (see for details). + The event parameter (see for details). + If successful, is returned, else is returned. Use to get the error code. + + Apart from the "global" events, all events apply only to the specified MIDI channel. + Except for the "non-MIDI" events, events applied to a MIDI file stream can subsequently be overridden by events in the file itself, and will also be overridden when seeking or looping. That can be avoided by using additional channels, allocated via the attribute. + Event syncs (BASS_SYNC_MIDI_xxx, see ) are not triggered by this function. If sync triggering is wanted, can be used instead. + If the MIDI stream is being played (it's not a decoding channel), then there will be some delay in the effect of the event being heard. + This latency can be reduced by making use of the BASS_CONFIG_BUFFER and BASS_CONFIG_UPDATEPERIOD config options when creating the stream. + If multiple events need to be applied at the same time, can be used instead of this function. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ILLPARAMOne of the other parameters is invalid. + + + + + Play the middle C note (key 60) with a velocity of 100, on channel 1 for 2 seconds: + + // press the key + BassMidi.BASS_MIDI_StreamEvent(handle, 0, BASSMIDIEvent.MIDI_EVENT_NOTE, 60, 100); + // wait 2 seconds + Thread.Sleep(2000); + // release the key + BassMidi.BASS_MIDI_StreamEvent(handle, 0, BASSMIDIEvent.MIDI_EVENT_NOTE, 60); + + + ' press the key + BassMidi.BASS_MIDI_StreamEvent(handle, 0, BASSMIDIEvent.MIDI_EVENT_NOTE, 60, 100) + ' wait 2 seconds + Thread.Sleep(2000) + ' release the key + BassMidi.BASS_MIDI_StreamEvent(handle, 0, BASSMIDIEvent.MIDI_EVENT_NOTE, 60) + + + + + + Applies an event to a MIDI stream. + + The MIDI stream to apply the event to (as returned by ). + The MIDI channel to apply the event in... 0 (channel 1) - 15 (channel 16). + The event to apply (see for details). + The event parameter (LOBYTE), (see for details). + The event parameter (HIBYTE), (see for details). + If successful, is returned, else is returned. Use to get the error code. + + Apart from the "global" events, all events apply only to the specified MIDI channel. + Except for the "non-MIDI" events, events applied to a MIDI file stream can subsequently be overridden by events in the file itself, and will also be overridden when seeking or looping. That can be avoided by using additional channels, allocated via the attribute. + Event syncs (BASS_SYNC_MIDI_xxx, see ) are not triggered by this function. If sync triggering is wanted, can be used instead. + If the MIDI stream is being played (it's not a decoding channel), then there will be some delay in the effect of the event being heard. + This latency can be reduced by making use of the BASS_CONFIG_BUFFER and BASS_CONFIG_UPDATEPERIOD config options when creating the stream. + If multiple events need to be applied at the same time, can be used instead of this function. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ILLPARAMOne of the other parameters is invalid. + + + + + Play the middle C note (key 60) with a velocity of 100, on channel 1 for 2 seconds: + + // press the key + BassMidi.BASS_MIDI_StreamEvent(handle, 0, BASSMIDIEvent.MIDI_EVENT_NOTE, 60, 100); + // wait 2 seconds + Thread.Sleep(2000); + // release the key + BassMidi.BASS_MIDI_StreamEvent(handle, 0, BASSMIDIEvent.MIDI_EVENT_NOTE, 60); + + + ' press the key + BassMidi.BASS_MIDI_StreamEvent(handle, 0, BASSMIDIEvent.MIDI_EVENT_NOTE, 60, 100) + ' wait 2 seconds + Thread.Sleep(2000) + ' release the key + BassMidi.BASS_MIDI_StreamEvent(handle, 0, BASSMIDIEvent.MIDI_EVENT_NOTE, 60) + + + + + + Applies any number of events to a MIDI stream (BASS_MIDI_EVENTS_STRUCT). + + The MIDI stream to apply the events to (as returned by ). + BASS_MIDI_EVENTS_STRUCT, with optional flags (see ): + + BASS_MIDI_EVENTS_RAWRaw MIDI event data, as would be sent to a MIDI device. Running status is supported. To overcome the 16 channel limit, the event data's channel information can optionally be overridden by adding the new channel number to this parameter, where +1 = the 1st channel. + BASS_MIDI_EVENTS_STRUCTAn array of structures. + BASS_MIDI_EVENTS_SYNCFlag: Trigger BASS_SYNC_MIDI_xxx syncs for the processed events (see ). + + + The event data (an array of structures). + If successful, the number of events processed is returned, else -1 is returned. Use to get the error code. + + Events applied to a MIDI file stream can subsequently be overridden by events in the file itself, and will also be overridden when seeking or looping. That can be avoided by using additional channels, allocated via the attribute. + If the MIDI stream is being played (it's not a decoding channel), then there will be some delay in the effect of the event being heard. + This latency can be reduced by making use of the BASS_CONFIG_BUFFER and BASS_CONFIG_UPDATEPERIOD config options when creating the stream. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ILLPARAM is not valid. + + + + + + + Applies any number of events to a MIDI stream (BASS_MIDI_EVENTS_RAW). + + The MIDI stream to apply the events to (as returned by ). + BASS_MIDI_EVENTS_RAW, with optional flags (see ): + + BASS_MIDI_EVENTS_RAWRaw MIDI event data, as would be sent to a MIDI device. Running status is supported. To overcome the 16 channel limit, the event data's channel information can optionally be overridden by adding the new channel number to this parameter, where +1 = the 1st channel. + BASS_MIDI_EVENTS_STRUCTAn array of structures. + BASS_MIDI_EVENTS_SYNCFlag: Trigger BASS_SYNC_MIDI_xxx syncs for the processed events (see ). + + + To overcome the 16 channel limit, the event data's channel information can optionally be overridden by adding the new channel number to this parameter, where 1 = the 1st channel - else leave to 0. + The event data (raw MIDI event data, as would be sent to a MIDI device). + If successful, the number of events processed is returned, else -1 is returned. Use to get the error code. + + Events applied to a MIDI file stream can subsequently be overridden by events in the file itself, and will also be overridden when seeking or looping. That can be avoided by using additional channels, allocated via the attribute. + If the MIDI stream is being played (it's not a decoding channel), then there will be some delay in the effect of the event being heard. + This latency can be reduced by making use of the BASS_CONFIG_BUFFER and BASS_CONFIG_UPDATEPERIOD config options when creating the stream. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ILLPARAM is not valid. + + + + + + + Applies any number of events to a MIDI stream (BASS_MIDI_EVENTS_RAW). + + The MIDI stream to apply the events to (as returned by ). + BASS_MIDI_EVENTS_RAW, with optional flags (see ): + + BASS_MIDI_EVENTS_RAWRaw MIDI event data, as would be sent to a MIDI device. Running status is supported. To overcome the 16 channel limit, the event data's channel information can optionally be overridden by adding the new channel number to this parameter, where +1 = the 1st channel. + BASS_MIDI_EVENTS_STRUCTAn array of structures. + BASS_MIDI_EVENTS_SYNCFlag: Trigger BASS_SYNC_MIDI_xxx syncs for the processed events (see ). + + + To overcome the 16 channel limit, the event data's channel information can optionally be overridden by adding the new channel number to this parameter, where 1 = the 1st channel - else leave to 0. + The pointer to the event data (e.g. as received in a ). + The number of bytes contained in the . + If successful, the number of events processed is returned, else -1 is returned. Use to get the error code. + + Events applied to a MIDI file stream can subsequently be overridden by events in the file itself, and will also be overridden when seeking or looping. That can be avoided by using additional channels, allocated via the attribute. + If the MIDI stream is being played (it's not a decoding channel), then there will be some delay in the effect of the event being heard. + This latency can be reduced by making use of the BASS_CONFIG_BUFFER and BASS_CONFIG_UPDATEPERIOD config options when creating the stream. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ILLPARAM is not valid. + + + + + + + Retrieves the current value of an event in a MIDI stream channel. + + The MIDI stream to retrieve the event from (as returned by ). + The MIDI channel to retrieve the event from... 0 (channel 1) - 15 (channel 16). + The event value to retrieve (see for details on the available event types and their values). + With the drum key events (MIDI_EVENT_DRUM_CUTOFF/etc) and the MIDI_EVENT_SCALETUNING event, the HIWORD - use Utils.MakeLong(event,key) - can be used to specify which key/note to get the value from. + The event parameter (see for details) if successful - else -1 (use to get the error code). + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ILLPARAMOne of the other parameters is invalid. + + + + + + + Retrieves the events in a MIDI file stream. + + The MIDI stream to get the events from. + The track to get the events from... 0 = 1st track. + The type of event to retrieve (use MIDI_EVENT_NONE to retrieve all events). See for a list of possible event types. + The pointer to an array of to retrieve the events ( = get the number of events without getting the events themselves). + If successful, the number of events is returned, else -1 is returned. Use to get the error code. + + This function should first be called with = to get the number of events, before allocating an array of the required size and retrieving the events. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe stream is for real-time events only, so does not have an event sequence. + BASS_ERROR_ILLPARAM is not valid. + + + + Retrieve all events in the 1st track: + + int eventCount = BassMidi.BASS_MIDI_StreamGetEvents(_stream, 0, BASSMIDIEvent.MIDI_EVENT_NONE); + BASS_MIDI_EVENT[] events = new BASS_MIDI_EVENT[eventCount]; + int count = BassMidi.BASS_MIDI_StreamGetEvents(_stream, 0, BASSMIDIEvent.MIDI_EVENT_NONE, events); + + + Dim eventCount = BassMidi.BASS_MIDI_StreamGetEvents(_stream, 0, BASSMIDIEvent.MIDI_EVENT_NONE) + Dim events(eventCount) As BASS_MIDI_EVENT + Dim count As Integer = BassMidi.BASS_MIDI_StreamGetEvents(_stream, 0, BASSMIDIEvent.MIDI_EVENT_NONE, events) + + + + + + Retrieves the events in a MIDI file stream. + + The MIDI stream to get the events from. + The track to get the events from... 0 = 1st track. + The type of event to retrieve (use MIDI_EVENT_NONE to retrieve all events). See for a list of possible event types. + An array of configuration entries if successfull - or on error. + This overload will always return all present event objects. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe stream is for real-time events only, so does not have an event sequence. + BASS_ERROR_ILLPARAM is not valid. + + + + Retrieve all note events in the 2nd track: + + BASS_MIDI_EVENT[] events = BassMidi.BASS_MIDI_StreamGetEvents(_stream, 1, BASSMIDIEvent.MIDI_EVENT_NOTE); + + + Dim events As BASS_MIDI_EVENT() = BassMidi.BASS_MIDI_StreamGetEvents(_stream, 1, BASSMIDIEvent.MIDI_EVENT_NOTE) + + + + + + Retrieves the number of events in a MIDI file stream. + + The MIDI stream to get the events from. + The track to get the events from... 0 = 1st track. + The type of event to retrieve (use MIDI_EVENT_NONE to retrieve all events). See for a list of possible event types. + If successful, the number of events is returned, else -1 is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe stream is for real-time events only, so does not have an event sequence. + BASS_ERROR_ILLPARAM is not valid. + + + + + + + Applies a soundfont configuration to a MIDI stream, or sets the default soundfont configuration. + + The MIDI stream to apply the soundfonts to... 0 = set default soundfont configuration. + The pointer to an array of soundfonts to apply. + The number of elements in the fonts array. + If successful, is returned, else is returned. Use to get the error code. + Multiple soundfonts can be stacked, to provide different presets and banks, for example. When a preset is present in multiple soundfonts, the earlier soundfont in the array has priority. + When a soundfont matching the MIDI file is loaded, that remains loaded when calling this function, and has priority over all other soundfonts. + Changing the default configuration only affects subsequently created MIDI streams. Existing streams that are using the previous default configuration will continue to use that previous configuration. + On Windows, the default default configuration will be to use the Creative 4MB (CT4MGM.SF2) or 2MB (CT2MGM.SF2) soundfont when present in the Windows system directory. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ILLPARAMSomething in the array is invalid, check the soundfont handles. + + + + + + // first initialize the fonts + int font1 = BassMidi.BASS_MIDI_FontInit("afont.sf2"); + int font2 = BassMidi.BASS_MIDI_FontInit("bfont.sf2"); + BASS_MIDI_FONT[] newfonts = { new BASS_MIDI_FONT(font1, -1, 0), new BASS_MIDI_FONT(font2, -1, 0) }; + // now set them + BassMidi.BASS_MIDI_StreamSetFonts(_stream, newfonts, newfonts.Length); + + + ' first initialize the fonts + Dim font1 As Integer = BassMidi.BASS_MIDI_FontInit("afont.sf2") + Dim font2 As Integer = BassMidi.BASS_MIDI_FontInit("bfont.sf2") + Dim newFonts() As BASS_MIDI_FONT = {New BASS_MIDI_FONT(font1, -1, 0), New BASS_MIDI_FONT(font2, -1, 0)} + ' now set them + BassMidi.BASS_MIDI_StreamSetFonts(_stream, newFonts, newFonts.Length) + + + + + + Retrieves the soundfont configuration of a MIDI stream, or the default soundfont configuration. + + The MIDI stream to retrieve the soundfont configuration of... 0 = get default soundfont configuration. + An array to retrieve the soundfont configuration. + The maximum number of elements to retrieve in the fonts array. This and fonts can be 0, to get the number of elements in the soundfont configuration. + If successful, the number of soundfonts in the configuration (which can be higher than count) is returned, else -1 is returned. Use to get the error code. + When a soundfont matching the MIDI file is loaded, it will be the first element in the returned configuration. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + int fontCount = BassMidi.BASS_MIDI_StreamGetFontsCount(_stream); + BASS_MIDI_FONT[] fonts = new BASS_MIDI_FONT[fontCount]; + int count = BassMidi.BASS_MIDI_StreamGetFonts(_stream, fonts, fontCount); + + + Dim fontCount As Integer = BassMidi.BASS_MIDI_StreamGetFontsCount(_stream) + Dim fonts(fontCount) As BASS_MIDI_FONT + Dim count As Integer = BassMidi.BASS_MIDI_StreamGetFonts(_stream, fonts, fontCount) + + + + + + Retrieves the soundfont configuration of a MIDI stream, or the default soundfont configuration. + + The MIDI stream to retrieve the soundfont configuration of... 0 = get default soundfont configuration. + An array of configuration entries if successfull - or on error. + This overload will always return all used soundfont configuration objects. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + BASS_MIDI_FONT[] fonts = BassMidi.BASS_MIDI_StreamGetFonts(_stream); + + + Dim fonts As BASS_MIDI_FONT() = BassMidi.BASS_MIDI_StreamGetFonts(_stream) + + + + + + Retrieves the number of elements in the soundfont configuration. + + The MIDI stream to retrieve the soundfont configuration of... 0 = get default soundfont configuration. + If successful, the number of soundfonts in the configuration is returned, else -1 is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + + Returns the total number of tracks contained in the MIDI stream. + + The MIDI stream to retrieve the track count from. + The number of tracks contained in the MIDI stream. + + + + Preloads the samples required by a MIDI file stream. + + The MIDI stream handle. + If successful, is returned, else is returned. Use to get the error code. + + Samples are normally loaded as they are needed while rendering a MIDI stream, which can result in CPU spikes, particularly with packed soundfonts. That generally won't cause any problems, but when smooth/constant performance is critical this function can be used to preload the samples before rendering, so avoiding the need to load them while rendering. + Preloaded samples can be compacted/unloaded just like any other samples, so it is probably wise to disable the BASS_CONFIG_MIDI_COMPACT option when preloading samples, to avoid any chance of the samples subsequently being automatically unloaded. + This function should not be used while the MIDI stream is being rendered, as that could interrupt the rendering. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe stream is for real-time events only, so it's not possible to know what presets are going to be used. Use instead. + + + + + + + Gets a HSTREAM handle for a MIDI channel (e.g. to set DSP/FX on individual MIDI channels). + + The midi stream to get a channel from. + The midi channel number for which to get an HSTREAM channel (0=channel 1). + If successful, the channel handle is returned, else 0 is returned. Use to get the error code. + + By default, MIDI channels do not have streams assigned to them; a MIDI channel only gets a stream when this function is called, which it then keeps until the MIDI stream is freed. + MIDI channel streams can also be freed before then via . Each MIDI channel stream increases the CPU usage slightly, even if there are no DSP/FX set on them, so for optimal performance they should not be activated when unnecessary + The MIDI channel streams have a different path to the final mix than the BASSMIDI reverb/chorus processing, which means that the reverb/chorus will not be present in the data received by any DSP/FX set on the streams and nor will the reverb/chorus be applied to the DSP/FX output; + the reverb/chorus processing will use the channel's original data. + The MIDI channel streams can only be used to set DSP/FX on the channels. + They cannot be used with or to visualise the channels, for example, + but that could be achieved via a DSP function instead. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAIL is not valid. + + + + + Apply some DX8 distortion to channel 1 of a MIDI stream: + + // get a stream for MIDI channel 1 + int chan1 = BassMidi.BASS_MIDI_StreamGetChannel(midi, 0); + // set the DX8 distortion effect on it + int fx = Bass.BASS_ChannelSetFX(chan1, BASSFXType.BASS_FX_DX8_DISTORTION, 0); + + + ' get a stream for MIDI channel 1 + Dim chan1 As Integer = BassMidi.BASS_MIDI_StreamGetChannel(midi, 0) + ' set the DX8 distortion effect on it + Dim chan1 As Integer = Bass.BASS_ChannelSetFX(chan1, BASSFXType.BASS_FX_DX8_DISTORTION, 0) + + + + + + + + + + + + + + Initializes a soundfont from a file (unicode). + + The file name of the sound font (e.g. an .sf2 file). + If successful, the soundfont's handle is returned, else 0 is returned. Use to get the error code. + The BASS_UNICODE flag is applied automatically here. + BASSMIDI uses SF2 soundfonts to provide the sounds to use in the rendering of MIDI files. Several SF2 soundfonts can be found on the internet, including one (Chorium) on the BASS website. + A soundfont needs to be initialized before it can be used to render MIDI streams. Once initialized, a soundfont can be assigned to MIDI streams using the function. A single soundfont can be shared by multiple MIDI streams. + Information on the initialized soundfont can be retrieved using . + If a soundfont is initialized multiple times, each instance will have its own handle but share the same sample/etc data. + + + ERROR CODEDescription + BASS_ERROR_FILEOPENThe could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + + + + + + // first initialize the fonts + int font1 = BassMidi.BASS_MIDI_FontInit("afont.sf2"); + int font2 = BassMidi.BASS_MIDI_FontInit("bfont.sf2"); + BASS_MIDI_FONT[] newfonts = new BASS_MIDI_FONT[2]; + newfonts[0] = new BASS_MIDI_FONT(font1, 10, 0); + newfonts[1] = new BASS_MIDI_FONT(font2, -1, 0); + // now set them + BassMidi.BASS_MIDI_StreamSetFonts(_stream, newfonts, 2); + + + ' first initialize the fonts + Dim font1 As Integer = BassMidi.BASS_MIDI_FontInit("afont.sf2") + Dim font2 As Integer = BassMidi.BASS_MIDI_FontInit("bfont.sf2") + Dim newfonts(2) As BASS_MIDI_FONT + newfonts(0) = New BASS_MIDI_FONT(font1, 10, 0) + newfonts(1) = New BASS_MIDI_FONT(font2, -1, 0) + BassMidi.BASS_MIDI_StreamSetFonts(_stream, newfonts, 2) + + + + + + Retrieves information on a soundfont. + + The soundfont to get info on (e.g. as returned by ). + An instance of the class to store the information at. + If successful, is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + int font1 = BassMidi.BASS_MIDI_FontInit("afont.sf2"); + BASS_MIDI_FONTINFO fontInfo = new BASS_MIDI_FONTINFO(); + BassMidi.BASS_MIDI_FontGetInfo(font1, fontInfo); + Console.WriteLine( fontInfo.ToString() ); + + + Dim font1 As Integer = BassMidi.BASS_MIDI_FontInit("afont.sf2") + Dim fontInfo As New BASS_MIDI_FONTINFO() + BassMidi.BASS_MIDI_FontGetInfo(font1, fontInfo) + Console.WriteLine(fontInfo.ToString()) + + + + + + Retrieves information on a soundfont. + + The soundfont to get info on (e.g. as returned by ). + An instance of the class on success - else . + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + + Compact a soundfont's memory usage. + + The soundfont to get info on (e.g. as returned by ). + If successful, is returned, else is returned. Use to get the error code. + Compacting involves freeing any samples that are currently loaded but unused. The amount of sample data currently loaded can be retrieved using . + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + + Frees a soundfont. + + The soundfont to get info on (e.g. as returned by ). + If successful, is returned, else is returned. Use to get the error code. + When a soundfont is freed, it is automatically removed from any MIDI streams that are using it. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + + + + + + + + + + + + Produces a compressed version of a soundfont. + Unicode version only here (BASS_UNICODE will be used automatically). + + The soundfont to pack. + Filename for the packed soundfont. + Encoder command-line (e.g. as returned by ). + If successful, the is returned, else is returned. Use to get the error code. + Standard soundfonts use PCM samples, so they can be quite large, which can be a problem if they're to be distributed. + To reduce the size, BASSMIDI can compress the samples using any command-line encoder with STDIN and STDOUT support. + Packed soundfonts can be used for rendering by BASSMIDI just like normal soundfonts. + They can also be unpacked using . + Although any command-line encoder can be used, it is best to use a lossless format like FLAC or WavPack, rather than a lossy one like OGG or MP3. + Using a lossless encoder, the packed soundfont will produce exactly the same results as the original soundfont, and will be identical to the original when unpacked. + As a compromise between quality and size, the WavPack hybrid/lossy mode also produces good sounding results. + The encoder must be told (via the command-line) to expect input from STDIN and to send it's output to STDOUT. + To use a packed soundfont, the appropriate BASS add-on needs to be loaded (via ) to decode the samples. + For example, if the samples are FLAC encoded, BASSFLAC would need to be loaded. During rendering, the samples are unpacked as they're needed, which could result in CPU spikes. + Where smooth performance is critical, it may be wise to preload the samples using . + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_FILEOPENCouldn't start the encoder. Check that the executable exists. + BASS_ERROR_CREATECouldn't create the output file, . + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Create a FLAC encoded version of a soundfont: + + // open original soundfont + int handle = BassMidi.BASS_MIDI_FontInit( "afile.sf2"); + // produce packed version + BassMidi.BASS_MIDI_FontPack(handle, "afile.sf2pack", "flac --best -"); + + + ' open original soundfont + Dim handle As Integer = BassMidi.BASS_MIDI_FontInit("afile.sf2") + ' produce packed version + BassMidi.BASS_MIDI_FontPack(handle, "afile.sf2pack", "flac --best -") + + Using the build-in encoder framework: + + EncoderFLAC flac = new EncoderFLAC(0); + flac.InputFile = null; // use STDIN + flac.OutputFile = null; // use STDOUT + // produce packed version + BassMidi.BASS_MIDI_FontPack(handle, "afile.sf2pack", flac.EncoderCommandLine); + + + Dim flac As New EncoderFLAC(0) + flac.InputFile = Nothing ' use STDIN + flac.OutputFile = Nothing ' use STDOUT + ' produce packed version + BassMidi.BASS_MIDI_FontPack(handle, "afile.sf2pack", flac.EncoderCommandLine) + + + + + + + + + + + + + + + Produces a decompressed version of a packed soundfont. + Unicode version only here (BASS_UNICODE will be used automatically). + + The soundfont to unpack. + Filename for the unpacked soundfont. + If successful, the is returned, else is returned. Use to get the error code. + To unpack a soundfont, the appropriate BASS add-on needs to be loaded (via ) to decode the samples. + For example, if the samples are FLAC encoded, BASSFLAC would need to be loaded. + BASS also needs to have been initialized, using . + For just unpacking a soundfont, the "no sound" device could be used. + can be used to check if a soundfont is packed. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe soundfont is not packed. + BASS_ERROR_INIT has not been successfully called - it needs to be to decode the samples. + BASS_ERROR_CODECThe appropriate add-on to decode the samples is not loaded. + BASS_ERROR_CREATECouldn't create the output file, . + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Unpack a FLAC encoded soundfont: + + // load FLAC plugin + Bass.BASS_PluginLoad("bassflac.dll"); + // open soundfont + int handle = BassMidi.BASS_MIDI_FontInit("afile.sf2pack"); + // produce unpacked version + BassMidi.BASS_MIDI_FontUnpack(handle, "afile.sf2"); + + + ' load FLAC plugin + Bass.BASS_PluginLoad("bassflac.dll") + ' open soundfont + Dim handle As Integer = BassMidi.BASS_MIDI_FontInit("afile.sf2pack") + ' produce unpacked version + BassMidi.BASS_MIDI_FontUnpack(handle, "afile.sf2") + + + + + + Preloads presets from a soundfont. + + The soundfont handle... 0 = all soundfonts. + Preset number to load... -1 = all presets. + Bank number to load... -1 = all banks. + If successful, is returned, else is returned. Use to get the error code. + + Samples are normally loaded as they are needed while rendering a MIDI stream, which can result in CPU spikes, particularly with packed soundfonts. That generally won't cause any problems, but when smooth/constant performance is critical this function can be used to preload the samples before rendering, so avoiding the need to load them while rendering. + When preloading samples to render a particular MIDI stream, it is more efficient to use to preload the specific samples that the MIDI stream will use, rather than preloading the entire soundfont. + Samples that are preloaded by this function are not affected by automatic compacting via the option, but can be compacted/unloaded manually with . + A soundfont should not be preloaded while it's being used to render any MIDI streams, as that could delay the rendering. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_CODECThe appropriate add-on to decode the samples is not loaded. + BASS_ERROR_NOTAVAILThe soundfont does not contain the requested preset. + + + + + + + Retrieves the name of a preset in a soundfont. + + + + + + + + + + + The soundfont handle to get the preset name from. + Preset number to load... -1 = all presets (the first encountered). + Bank number to load... -1 = all banks (the first encountered). + If successful, the requested preset name is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe soundfont does not contain the requested preset. + + + + + + + Sets a soundfont's volume level. + + The soundfont to set the volume of. + The volume level... 0=silent, 1.0=normal/default. + If successful, is returned, else is returned. Use to get the error code. + + By default, some soundfonts may be louder than others, which could be a problem when mixing multiple soundfonts. + This function can be used to compensate for any differences, by raising the level of the quieter soundfonts or lowering the louder ones. + Changes take immediate effect in any MIDI streams that are using the soundfont. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + + Retrieves a soundfont's volume level. + + The soundfont to get the volume of. + If successful, the soundfont's volume level is returned, else -1 is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + + + + + + + + + + Retrieves information on a MIDI input device. + + The device to get the information of... 0 = first. + An instance of the class to store the information at. + If successful, then is returned, else is returned. Use to get the error code. + This function can be used to enumerate the available MIDI input devices for a setup dialog. + + + ERROR CODEDescription + BASS_ERROR_DEVICEThe device number specified is invalid. + + + Platform-specific + MIDI input is not available on iOS. + + + + + Retrieves information on a MIDI input device. + + The device to get the information of... 0 = first. + If successful, an instance of the class is returned, else is returned. Use to get the error code. + This function can be used to enumerate the available MIDI input devices for a setup dialog. + + + ERROR CODEDescription + BASS_ERROR_DEVICEThe device number specified is invalid. + + + Platform-specific + MIDI input is not available on iOS. + + + + + Returns all available MIDI input devices. + + An array of elements representing the available MIDI input devices. + Uses internally. + + + + Returns the total number of available MIDI input devices. + + Number of real MIDI input devices available. + Uses internally. + + + + Initializes a MIDI input device. + + The device to use... 0 = first. can be used to enumerate the available devices. + Callback delegate to receive MIDI data from the device. + User instance data to pass to the callback delegate. + If the device was successfully initialized, is returned, else is returned. Use to get the error code. + + This function must be successfully called before using any MIDI input functions. + + + ERROR CODEDescription + BASS_ERROR_DEVICEThe device number specified is invalid. + BASS_ERROR_ALREADYThe device has already been initialized. You must call before you can initialize it again. + BASS_ERROR_NOTAVAILThe device is not available. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + MIDI input is not available on iOS. + + + + + Frees a MIDI input device. + + The device to free. + If successful, is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_DEVICEThe device number specified is invalid. + BASS_ERROR_INITThe device has not been initialized. + + + + + + + Starts a MIDI input device. + + The device to start. + If successful, is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_DEVICEThe device number specified is invalid. + BASS_ERROR_INITThe device has not been initialized. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Stops a MIDI input device. + + The device to stop. + If successful, is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_DEVICEThe device number specified is invalid. + BASS_ERROR_INITThe device has not been initialized. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Supported file extensions of the bassmidi.dll + + + + + Supported file format name of the bassmidi.dll + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + The disadvantage of this method is, that the standard plugin support for is not working - so you would need to use the native add-on methods! + + + Load BASS and BASSMIDI from the application's startup path: + + Bass.LoadMe(); + BassMidi.LoadMe(); + ... + // when not used anymore... + BassMidi.FreeMe(); + Bass.FreeMe(); + + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + Load BASS and BASSMIDI from a different directory: + + Bass.LoadMe( @"C:\Development\BASS\_libs" ); + BassMidi.LoadMe( @"C:\Development\BASS\_libs" ); + ... + // when not used anymore... + BassMidi.FreeMe(); + Bass.FreeMe(); + + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + The Marker type, to be used with . + + + + + Marker events. + + + + + Cue events. + + + + + Lyric events. + + + + + Text events. + + + + + Time signature event (MIDI meta event 88). + The time signature events are given in the form of "numerator/denominator metronome-pulse 32nd-notes-per-MIDI-quarter-note", eg. "4/4 24 8" + + + + + Key signature event. + That gives the key signature (in BASS_MIDI_MARK.text) in the form of "a b", where "a" is the number of sharps (if positive) or flats (if negative) and "b" signifies major (if 0) or minor (if 1). + + + + + FLAG: get position in ticks instead of bytes + + + + + The MIDI event type, to be used with resp. or . + + + + + + + No event. + + + + + Press a key. + param : LOBYTE = key number (0-127), HIBYTE = velocity (0-127). + + + + + Select the preset/instrument to use. Standard soundfont presets follow the General MIDI standard, and generally also include Roland GS variations in other banks (accessible via the MIDI_EVENT_BANK event). + param : preset number (0-127). + + + + + Set the channel pressure. + param : pressure level (0-127). + + + + + Set the pitch wheel. + param : pitch wheel position (0-16383, 8192=normal/middle). + + + + + Set pitch wheel range (MIDI RPN 0). + param : range in semitones. + + + + + Set the percussion/drums channel switch. The bank and program are reset to 0 when this changes. + param : use drums? (0=no, 1=yes). + + + + + Set the fine tuning (MIDI RPN 1). + param : finetune in cents (0-16383, 0=-100, 8192=normal, 16383=+100). + + + + + Set the coarse tuning (MIDI RPN 2). + param : finetune in semitones (0-127, 0=-64, 64=normal, 127=+63). + + + + + Set the master volume. + param : volume level (0-16383, 0=silent, 16363=normal/full). + + + + + Select the bank to use (MIDI controller 0). + param : bank number (0-127). + + + + + Set the modulation (MIDI controller 1). + param : modulation level (0-127). + + + + + Set the volume (MIDI controller 7). + param : volume level (0-127). + + + + + Set the pan position (MIDI controller 10). + param : pan position (0-127, 64=middle). + + + + + Set the expression (MIDI controller 11). + param : expression level (0-127). + + + + + Set the sustain switch (MIDI controller 64). + param : enable sustain? (0-63=no, 64-127=yes). + + + + + Stop all sounds (MIDI controller 120). + param : not used. + + + + + Reset controllers (MIDI controller 121), that is modulation=0, expression=127, sustain=0, pitch wheel=8192, channel pressure=0. + param : not used. + + + + + Release all keys (MIDI controller 123). + param : not used. + + + + + Set the portamento switch (MIDI controller 65). + param : enable portamento? (0-63=no, 64-127=yes). + + + + + Set the portamento time (MIDI controller 5). + param : portamento time (0-127). + + + + + Set the portamento start key - the next note starts at this key (MIDI controller 84). + param : key number (1-127, 60=middle C). + + + + + Set poly/mono mode (MIDI controllers 126 & 127). + param : mode (0=poly, 1=mono). + + + + + Set the reverb send level (MIDI controller 91). + param : reverb level (0-127). + + + + + Set the chorus send level (MIDI controller 93). + param : chorus level (0-127). + + + + + Set the low-pass filter cutoff (MIDI controller 74, NRPN 120h). + param : cutoff level (0-127, 0=-64, 64=normal, 127=+63). + + + + + Set the low-pass filter resonance (MIDI controller 71, NRPN 121h). + param : resonance level (0-127, 0=-64, 64=normal, 127=+63). + + + + + Set the release time (MIDI controller 72, NRPN 166h). + param : release time (0-127, 0=-64, 64=normal, 127=+63). + + + + + Set the attack time (MIDI controller 73, NRPN 163h). + param : attack time (0-127, 0=-64, 64=normal, 127=+63). + + + + + To be defined. + param : to be defined. + + + + + To be defined. + param : to be defined. + + + + + Set the reverb time. + param : reverb time in milliseconds. + + + + + Set the reverb delay. + param : reverb delay in millisecond 10ths. + + + + + Set the reverb low-pass cutoff. + param : reverb low-pass cutoff in hertz (0=off). + + + + + Set the reverb high-pass cutoff. + param : reverb high-pass cutoff in hertz (0=off). + + + + + Set the reverb level. + param : reverb level (0=off, 100=0dB, 200=+6dB). + + + + + Set the chorus delay. + param : chorus delay in millisecond 10ths. + + + + + Set the chorus depth. + param : chorus depth in millisecond 10ths. + + + + + Set the chorus rate. + param : chorus rate in hertz 100ths. + + + + + Set the chorus feedback level. + param : chorus feedback level (0=-100%, 100=off, 200=+100%). + + + + + Set the chorus level. + param : chorus level (0=off, 100=0dB, 200=+6dB). + + + + + Set the chorus send to reverb level. + param : chorus send to reverb level (0=off, 100=0dB, 200=+6dB). + + + + + Set the fine tuning of a drum key (MIDI NRPN 19knh). + param : LOBYTE = key number (0-127), HIBYTE = finetune in cents (0-127, 0=-100, 64=normal, 127=+100). + + + + + Set the coarse tuning of a drum key (MIDI NRPN 18knh). + param : LOBYTE = key number (0-127), HIBYTE = finetune in semitones (0-127, 0=-64, 64=normal, 127=+63). + + + + + Set the pan position of a drum key (MIDI NRPN 1Cknh). + param : LOBYTE = key number (0-127), HIBYTE = pan position (0-127, 0=random, 64=middle). + + + + + Set the reverb send level of a drum key (MIDI NRPN 1Dknh). + param : LOBYTE = key number (0-127), HIBYTE = reverb level (0-127). + + + + + Set the chorus send level of a drum key (MIDI NRPN 1Eknh). + param : LOBYTE = key number (0-127), HIBYTE = chorus level (0-127). + + + + + Set the low-pass filter cutoff of a drum key (MIDI NRPN 14knh). + param : LOBYTE = key number (0-127), HIBYTE = cutoff level (0-127, 0=-64, 64=normal, 127=+63). + + + + + Set the low-pass filter resonance of a drum key (MIDI NRPN 15knh). + param : LOBYTE = key number (0-127), HIBYTE = resonance level (0-127, 0=-64, 64=normal, 127=+63). + + + + + Set the drum level NRPN of a drum key (MIDI NRPN 16knh). + param : LOBYTE = key number (0-127), HIBYTE = level (0-127, 127=full/normal). + + + + + Set the soft pedal/switch (MIDI controller 67). + param : soft is on? (0-63=no, 64-127=yes). + + + + + Set the system mode, resetting everything to the system's defaults. + MIDI_SYSTEM_DEFAULT is identical to MIDI_SYSTEM_GS, except that channel 10 is melodic if there are not 16 channels. MIDI_EVENT_SYSTEM does not reset things in any additional channels allocated to a MIDI file stream via the attribute, while MIDI_EVENT_SYSTEMEX does. + param : system mode (see ). + + + + + Set the tempo (MIDI meta event 81). Changing the tempo affects the stream length, and the value will no longer be valid. + param : tempo in microseconds per quarter note. + + + + + Set the tuning of a note in every octave. + param : LOWORD = tuning change in cents (0-16383, 0=-100, 8192=normal, 16383=+100), HIWORD = note (0-11, 0=C). + + + + + Set the level. + param : the level (0=silent, 100=0dB, 200=+6dB). + + + + + Transpose all notes. Changes take effect from the next note played, and affect melodic channels only (not drum channels). + param : transposition amount in semitones (0=-100, 100=normal, 200=+100). + + + + + Set the system mode, resetting everything to the system's defaults. + MIDI_SYSTEM_DEFAULT is identical to MIDI_SYSTEM_GS, except that channel 10 is melodic if there are not 16 channels. MIDI_EVENT_SYSTEM does not reset things in any additional channels allocated to a MIDI file stream via the attribute, while MIDI_EVENT_SYSTEMEX does. + param : system mode (see ). + + + + + Used with to mark the end of a track (the next event will be in a new track). + + + + + Used with to mark the end of the event array. + + + + + System mode parameter, to be used with , . + + + MIDI_SYSTEM_DEFAULT is identical to MIDI_SYSTEM_GS, except that channel 10 is melodic if there are not 16 channels. + + + + + System default. + + + + + General MIDI Level 1. + + + + + General MIDI Level 2. + + + + + XG-Format (Yamaha). + + + + + GS-Format (Roland). + + + + + The type of event data to apply, to be used with . + + + + + An array of structures. + + + + + Raw MIDI event data, as would be sent to a MIDI device. + Running status is supported. To overcome the 16 channel limit, the event data's channel information can optionally be overridden by adding the new channel number to this parameter, where +1 = the 1st channel. + + + + + Trigger BASS_SYNC_MIDI_xxx syncs for the processed events (see ). + + + + + Used with to retrieve information on a soundfont. + + + The name, copyright and comment members can be if the soundfont file does not include that information. + + + + + Name of the soundfont. + + + + + Copyright notice. + + + + + Any comments. + + + + + The number of presets/instruments in the soundfont. + + + + + The total size (in bytes) of the sample data in the soundfont. + + + + + The amount of sample data currently loaded. + + + + + The BASS_CTYPE_STREAM_xxx format of the sample data if it's packed... -1 = unknown format (appropriate BASS add-on not loaded), 0 = not packed. + + + + + Default constructor. + + + + + A description of the soundfont info object (name, copyright, comment, size etc.) + + The string description of the soundfont info object. + + + + Used with and to set and retrieve soundfont configurations. + + When using an individual preset from a soundfont, BASSMIDI will first look for the exact preset and bank match, but if that's not present, the first preset from the soundfont will be used. This is useful for single preset soundfonts. + When using all presets in a soundfont, the bank member is a base number that's added to the soundfont's banks. For example, if bank=1 then the soundfont's bank 0 becomes bank 1, etc... Negative base numbers are allowed. + + + + + Soundfont handle, previously inititialized with . + + + + + Preset number... -1 = use all presets in the soundfont. + + + + + Base bank number, or the bank number of the individual preset. + + + + + Constructor already setting the members. + + The soundfont handle to use. + The preset number to use (-1=use all presets). + The bank number to use. + + + + A description of the soundfont configuration object (font, preset, bank) + + The description string of the soundfont configuration object. + + + + Used with , , and to retrieve markers. + + + + + The MIDI track (number) containing marker (0=first). + + + + + The position (in bytes) of the marker. + + + + + The marker, cue, lyric, keysig, timesig text. + + If the lyric text begins with a '/' (slash) character, a new line should be started. + If it begins with a '\' (backslash) character, the display should be cleared. + For a key signature event (MIDI meta event 89). The marker text is in the form of "a b", where a is the number of sharps (if positive) or flats (if negative), and b signifies major (if 0) or minor (if 1). + For a time signature events (MIDI meta event 88). The marker text is in the form of "a/b c d", where a is the numerator, b is the denominator, c is the metronome pulse, and d is the number of 32nd notes per MIDI quarter-note + + + + + Default Constructor. + + + + + Constructor already setting the members. + + The track (number) containing marker. + The position (in bytes) of the marker. + The marker text. + + + + A description of the marker object (the text). + + The marker description text. + + + + Used with to retrieve events. + + + + + The event type (see ). + + + + + The event parameter. + + + + + The MIDI channel of the event... 0 = channel 1. + + + + + The position of the event, in ticks. + + + + + The position of the event, in bytes. + + + + + Constructor already setting the members. + + The event type. + The event parameter. + The MIDI channel of the event... 0 = channel 1. + The position of the event, in ticks. + The position of the event, in bytes. + + + + A description of the MIDI event object (event, param, chan, tick) + + The description string of the MIDI event object. + + + + Used with to retrieve information on a MIDI input device. + + + On Windows, id consists of a manufacturer identifier in the LOWORD and a product identifier in the HIWORD. This will not uniquely identify a particular device, ie. multiple devices may have the same value. + A list of identifiers is available from Microsoft, here. + On OSX, id is the device's "kMIDIPropertyUniqueID" property value, which is unique to the device. + + + + + The name/description of the device. + + + + + An identification number. + + + On Windows, id consists of a manufacturer identifier in the LOWORD and a product identifier in the HIWORD. This will not uniquely identify a particular device, ie. multiple devices may have the same value. + A list of identifiers is available from Microsoft, here. + On OSX, id is the device's "kMIDIPropertyUniqueID" property value, which is unique to the device. + + + + + The device's current status. A combination of these flags (): + + BASS_DEVICE_ENABLEDThe device is enabled. It will not be possible to initialize the device if this flag is not present. + BASS_DEVICE_INITThe device is initialized, ie. has been called. + + + + + + Default constructor. + + + + + A description of the decive info object (name). + + A description of the decive info object (name). + + + + The device is enabled and can be used. + + + + + The device is already initialized. + + + + + User defined callback delegate to receive MIDI data (to be used with ). + + The MIDI input device that the data is from. + Timestamp, in seconds since was called. + Pointer to the MIDI data. + The amount of data in bytes. + The user instance data given when was called. + + + private MIDIINPROC _midiProc; + private int _midiStream; + ... + // create a MIDI input callback delegate + _midiProc = new MIDIINPROC(MyMidiInProc); + BassMidi.BASS_MIDI_InInit(0, _midiProc, IntPtr.Zero); + ... + // create a MIDI stream to play the MIDI data + _midiStream = BassMidi.BASS_MIDI_StreamCreate(16, BASSFlag.BASS_DEFAULT, 44100); + ... + private void MyMidiInProc(int device, double time, IntPtr buffer, int length, IntPtr user) + { + // forward the data to the MIDI stream + BassMidi.BASS_MIDI_StreamEvents(_midiStream, BASSMIDIEventMode.BASS_MIDI_EVENTS_NONE, 0, buffer, length); + } + + + Private _midiProc As MIDIINPROC + Private _midiStream As Integer + ... + ' create a MIDI input callback delegate + _midiProc = New MIDIINPROC(AddressOf MyMidiInProc) + BassMidi.BASS_MIDI_InInit(0, _midiProc, IntPtr.Zero); + ... + ' create a MIDI input callback delegate + _midiStream = BassMidi.BASS_MIDI_StreamCreate(16, BASSFlag.BASS_DEFAULT, 44100) + ... + Private Procedure MyMidiInProc(handle As Integer, buffer As IntPtr, length As Integer, user As IntPtr) + ' forward the data to the MIDI stream + BassMidi.BASS_MIDI_StreamEvents(_midiStream, BASSMIDIEventMode.BASS_MIDI_EVENTS_NONE, 0, buffer, length) + End Procedure + + + + + + BASS.NET API wrapper for BASSENC.DLL + Requires: bassenc.dll - Encoding support library - available @ www.un4seen.com. + + + BASSenc is an extension that allows BASS channels to be encoded using any command-line encoder that has STDIN support (LAME/OGGENC/etc). + + + + + Current BASSenc version (without minor revision). + + + + + NOT used - all members are static! + + + + + Retrieves the version number of the BASSenc.DLL that is loaded. + + The BASSenc version. For example, 0x02040103 (hex), would be version 2.4.1.3. + There is no guarantee that a previous or future version of BASSenc supports all the BASSenc functions that you are using, so you should always use this function to make sure the correct version is loaded. + It is safe to assume that future minor revisions (indicated in the LOWORD) will be fully compatible. + You might use the global constant to check the major revision. + Note: Calling this method will also automatically load the library into memory. + + + Checking the major version only: + + if ( Utils.HighWord(BassEnc.BASS_Encode_GetVersion()) != BassEnc.BASSENCVERSION ) + { + MessageBox.Show(this, "Wrong BassEnc Version!"); + } + + + If Utils.HighWord(BassEnc.BASS_Encode_GetVersion()) <> BassEnc.BASSENCVERSION Then + MessageBox.Show(Me, "Wrong BassEnc Version!") + End If + + Checking for full version "2.4.1.3": + + if (BassEnc.BASS_Encode_GetVersion() < Utils.MakeLong(0x0103, 0x0204)) + { + MessageBox.Show(this, "Wrong BassEnc Version!"); + } + + + If BassEnc.BASS_Encode_GetVersion() < Utils.MakeLong(&H103, &H204) Then + MessageBox.Show(Me, "Wrong BassEnc Version!") + End If + + + + + + Retrieves the version of the BASSenc.DLL that is loaded. + + The number of components to use. The fieldCount ranges from 1 to 4 (major.minor.build.revision). + The BASSenc version (major.minor.build.revision). + There is no guarantee that a previous or future version of BASSenc supports all the BASSenc functions that you are using, so you should always use this function to make sure the correct version is loaded. + It is safe to assume that future minor revisions (indicated in the LOWORD) will be fully compatible. + Note: Calling this method will also automatically load the library into memory. + + + + Version expectedVersion = new Version(2, 4); + if (BassEnc.BASS_Encode_GetVersion(2) < expectedVersion) + { + MessageBox.Show( this, "Wrong BassEnc Version!" ); + } + + + Dim expectedVersion As New Version(2, 4) + If BassEnc.BASS_Encode_GetVersion(2) < expectedVersion Then + MessageBox.Show(Me, "Wrong BassEnc Version!") + End If + + + + + + + + + + + + + + + + + Starts encoding on a channel. + This overload implements UNICODE cmdlines. The BASS_UNICODE flag will be added automatically, since all .Net strings are always unicode. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + The encoder command-line, including the executable filename and any options. Or the output filename if the BASS_ENCODE_PCM flag is specified. + A combination of these flags (see ): + + BASS_ENCODE_PCMWrite plain PCM sample data to a file, without an encoder. The output filename is given in the cmdline parameter, or it can be to not write a file. + BASS_ENCODE_RF64Write a BWF RF64 WAVE header instead of a standard header. + BASS_ENCODE_NOHEADDon't send a WAVE header to the encoder. If this flag is used then the sample format must be passed to the encoder some other way (eg. via the command-line). + BASS_ENCODE_BIGENDSend big-endian sample data to the encoder, else little-endian. + BASS_ENCODE_FP_8BIT, BASS_ENCODE_FP_16BIT, BASS_ENCODE_FP_24BIT, BASS_ENCODE_FP_32BITWhen you want to encode a floating-point channel, but the encoder does not support 32-bit floating-point sample data, then you can use one of these flags to have the sample data converted to 8/16/24/32 bit integer data before it's passed on to the encoder. These flags are ignored if the channel's sample data isn't floating-point. + BASS_ENCODE_QUEUEQueue data to feed the encoder asynchronously. This prevents the data source (DSP system or call) getting blocked by the encoder, but if data is queud more quickly than the encoder can process it, that could result in lost data. + BASS_ENCODE_PAUSEStart the encoder paused. + BASS_ENCODE_MONOConvert to mono (if not already). + BASS_ENCODE_AUTOFREEAutomatically free the encoder when the source channel is freed. + BASS_ENCODE_CAST_NOLIMITDon't limit the data rate (to real-time speed) when sending to a Shoutcast or Icecast server. + BASS_ENCODE_LIMITLimit the data rate to real-time speed, by introducing a delay when the rate is too high. With BASS 2.4.6 or above, this flag is ignored when the encoder is fed in a playback buffer update cycle (including and calls), to avoid possibly causing playback buffer underruns. Except for in those instances, this flag is applied automatically when the encoder is feeding a Shoutcast or Icecast server. + BASS_UNICODEcmdline is Unicode (16-bit characters) (not needed here, since the overloads already take care of it). + + + Optional callback function to receive the encoded data... = no callback. To have the encoded data received by a callback function, the encoder needs to be told to output to STDOUT (instead of a file). + User instance data to pass to the callback function. + The encoder process handle is returned if the encoder is successfully started, else 0 is returned (use to get the error code). + + The encoder must be told (via the command-line) to expect input from STDIN, rather than a file. The command-line should also tell the encoder what filename to write it's output to, unless you're using a callback function, in which case it should be told to write it's output to STDOUT. + No user interaction with the encoder is possible, so anything that would cause the encoder to require the user to press any keys should be avoided. For example, if the encoder asks whether to overwrite files, the encoder should be instructed to always overwrite (via the command-line), or you should delete the existing file before starting the encoder. + Standard RIFF files are limited to a little over 4GB in size. When writing a WAV file, BASSenc will automatically stop at that point, so that the file is valid. That does not apply when sending data to an encoder though, as the encoder may (possibly via a command-line option) ignore the size restriction, but if it does not, it could mean that the encoder stops after a few hours (depending on the sample format). If longer encodings are needed, the BASS_ENCODE_NOHEAD flag can be used to omit the WAVE header, and the encoder informed of the sample format via the command-line instead. The 4GB size limit can also be overcome with the BASS_ENCODE_RF64 flag, but most encoders are unlikely to support RF64. + When writing an RF64 WAV file, a standard RIFF header will still be written initially, which will only be replaced by an RF64 header at the end if the file size has exceeded the standard limit. When an encoder is used, it is not possible to go back and change the header at the end, so the RF64 header is sent at the beginning in that case. + Internally, the sending of sample data to the encoder is implemented via a DSP callback on the channel. That means when you play the channel (or call if it's a decoding channel), the sample data will be sent to the encoder at the same time. + It also means that if you use the BASS_CONFIG_FLOATDSP option, then the sample data will be 32-bit floating-point, and you'll need to use one of the BASS_ENCODE_FP flags if the encoder does not support floating-point sample data. + The BASS_CONFIG_FLOATDSP setting should not be changed while encoding is in progress. + The encoder DSP has a priority setting of -1000, so if you want to set DSP/FX on the channel and have them present in the encoding, set their priority above that. + Besides the automatic DSP system, data can also be manually fed to the encoder via the function. Both methods can be used together, but in general, the "automatic" system ought be paused when using the "manual" system, by use of the BASS_ENCODE_PAUSE flag or the function. + When queued encoding is enabled via the BASS_ENCODE_QUEUE flag, the DSP system or call will just buffer the data, and the data will then be fed to the encoder by another thread. The buffer will grow as needed to hold the queued data, up to a limit specified by the BASS_CONFIG_ENCODE_QUEUE config option. + If the limit is exceeded (or there is no free memory), data will be lost; can be used to be notified of that occurrence. The amount of data that is currently queued, as well as the queue limit and how much data has been lost, is available from . + can be used to check that the encoder is still running. When done encoding, use to close the encoder. + The returned process handle can be used to do things like change the encoder's priority and get it's exit code. See the System.Diagnostics namespace for details. + Multiple encoders can be set on a channel. For simplicity, the encoder functions (ie. BASS_Encode_IsActive/SetPaused/Stop/Write) will accept either an encoder handle or a channel handle. When using a channel handle, the function is applied to all encoders that are set on that channel. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_FILEOPENCouldn't start the encoder. Check that the executable exists. + BASS_ERROR_CREATEThe PCM file couldn't be created. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + External encoders are not supported on iOS or Windows CE, so only plain PCM file writing with the BASS_ENCODE_PCM flag is possible on those platforms. + + + Start encoding a channel to an MP3 file (output.mp3) using LAME with the standard preset settings: + + BassEnc.BASS_Encode_Start(channel, "lame --alt-preset standard - output.mp3", + 0, null, IntPtr.Zero); + // start the channel playing & encoding + Bass.BASS_ChannelPlay(channel, false); + + + BassEnc.BASS_Encode_Start(channel, "lame --alt-preset standard - output.mp3", + 0, Nothing, IntPtr.Zero) + ' start the channel playing & encoding + Bass.BASS_ChannelPlay(channel, False) + + Start writing a channel to a WAV file (output.wav): + + BassEnc.BASS_Encode_Start(channel, "output.wav", + BASSEncode.BASS_ENCODE_PCM, null, IntPtr.Zero); + // start the channel playing & encoding + Bass.BASS_ChannelPlay(channel, false); + + + BassEnc.BASS_Encode_Start(channel, "output.wav", + BASSEncode.BASS_ENCODE_PCM, Nothing, IntPtr.Zero) + ' start the channel playing & encoding + Bass.BASS_ChannelPlay(channel, False) + + + + + + + + + + + + + + + + + + Starts encoding on a channel. + This overload implements UNICODE cmdlines. The BASS_UNICODE flag will be added automatically, since all .Net strings are always unicode. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + The encoder command-line, including the executable filename and any options. Or the output filename if the BASS_ENCODE_PCM flag is specified. + A combination of these flags (see ): + + BASS_ENCODE_PCMWrite plain PCM sample data to a file, without an encoder. The output filename is given in the cmdline parameter, or it can be to not write a file. + BASS_ENCODE_RF64Write a BWF RF64 WAVE header instead of a standard header. + BASS_ENCODE_NOHEADDon't send a WAVE header to the encoder. If this flag is used then the sample format must be passed to the encoder some other way (eg. via the command-line). + BASS_ENCODE_BIGENDSend big-endian sample data to the encoder, else little-endian. + BASS_ENCODE_FP_8BIT, BASS_ENCODE_FP_16BIT, BASS_ENCODE_FP_24BIT, BASS_ENCODE_FP_32BITWhen you want to encode a floating-point channel, but the encoder does not support 32-bit floating-point sample data, then you can use one of these flags to have the sample data converted to 8/16/24/32 bit integer data before it's passed on to the encoder. These flags are ignored if the channel's sample data isn't floating-point. + BASS_ENCODE_QUEUEQueue data to feed the encoder asynchronously. This prevents the data source (DSP system or call) getting blocked by the encoder, but if data is queud more quickly than the encoder can process it, that could result in lost data. + BASS_ENCODE_PAUSEStart the encoder paused. + BASS_ENCODE_AUTOFREEAutomatically free the encoder when the source channel is freed. + BASS_ENCODE_CAST_NOLIMITDon't limit the data rate (to real-time speed) when sending to a Shoutcast or Icecast server. + BASS_ENCODE_LIMITLimit the data rate to real-time speed, by introducing a delay when the rate is too high. With BASS 2.4.6 or above, this flag is ignored when the encoder is fed in a playback buffer update cycle (including and calls), to avoid possibly causing playback buffer underruns. Except for in those instances, this flag is applied automatically when the encoder is feeding a Shoutcast or Icecast server. + BASS_UNICODEcmdline is Unicode (16-bit characters) (not needed here, since the overloads already take care of it). + + + Optional callback function to receive the encoded data... = no callback. To have the encoded data received by a callback function, the encoder needs to be told to output to STDOUT (instead of a file). + User instance data to pass to the callback function. + The maximum number of bytes that will be encoded (0=no limit). + The encoder process handle is returned if the encoder is successfully started, else 0 is returned (use to get the error code). + + This function works exactly like , but with a parameter added, which is the maximum number of bytes that will be encoded (0=no limit). + Once the limit is hit, the encoder will die. can be used to be notified of that occurrence. + One thing to note is that the limit is applied after any conversion due to the BASS_ENCODE_FP flags. + This can be useful in situations where the encoder needs to know in advance how much data it will be receiving. For example, when using a callback function with a file format that stores the length in the header, as the header cannot then be updated at the end of encoding. The length is communicated to the encoder via the WAVE header, so it requires that the BASS_ENCODE_NOHEAD flag is not used. + The encoder must be told (via the command-line) to expect input from STDIN, rather than a file. The command-line should also tell the encoder what filename to write it's output to, unless you're using a callback function, in which case it should be told to write it's output to STDOUT. + No user interaction with the encoder is possible, so anything that would cause the encoder to require the user to press any keys should be avoided. For example, if the encoder asks whether to overwrite files, the encoder should be instructed to always overwrite (via the command-line), or you should delete the existing file before starting the encoder. + Internally, the sending of sample data to the encoder is implemented via a DSP callback on the channel. That means when you play the channel (or call if it's a decoding channel), the sample data will be sent to the encoder at the same time. + It also means that if you use the BASS_CONFIG_FLOATDSP option, then the sample data will be 32-bit floating-point, and you'll need to use one of the BASS_ENCODE_FP flags if the encoder does not support floating-point sample data. + The BASS_CONFIG_FLOATDSP setting should not be changed while encoding is in progress. + The encoder DSP has a priority setting of -1000, so if you want to set DSP/FX on the channel and have them present in the encoding, set their priority above that. + Besides the automatic DSP system, data can also be manually fed to the encoder via the function. Both methods can be used together, but in general, the "automatic" system ought be paused when using the "manual" system, by use of the BASS_ENCODE_PAUSE flag or the function. + When queued encoding is enabled via the BASS_ENCODE_QUEUE flag, the DSP system or call will just buffer the data, and the data will then be fed to the encoder by another thread. The buffer will grow as needed to hold the queued data, up to a limit specified by the BASS_CONFIG_ENCODE_QUEUE config option. + If the limit is exceeded (or there is no free memory), data will be lost; can be used to be notified of that occurrence. The amount of data that is currently queued, as well as the queue limit and how much data has been lost, is available from . + can be used to check that the encoder is still running. When done encoding, use to close the encoder. + The returned process handle can be used to do things like change the encoder's priority and get it's exit code. See the System.Diagnostics namespace for details. + Multiple encoders can be set on a channel. For simplicity, the encoder functions (ie. BASS_Encode_IsActive/SetPaused/Stop/Write) will accept either an encoder handle or a channel handle. When using a channel handle, the function is applied to all encoders that are set on that channel. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_FILEOPENCouldn't start the encoder. Check that the executable exists. + BASS_ERROR_CREATEThe PCM file couldn't be created. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + External encoders are not supported on iOS or Windows CE, so only plain PCM file writing with the BASS_ENCODE_PCM flag is possible on those platforms. + + + Start encoding a channel to an MP3 file (output.mp3) using LAME with the standard preset settings: + + BassEnc.BASS_Encode_Start(channel, "lame --alt-preset standard - output.mp3", + 0, null, IntPtr.Zero); + // start the channel playing & encoding + Bass.BASS_ChannelPlay(channel, false); + + + BassEnc.BASS_Encode_Start(channel, "lame --alt-preset standard - output.mp3", + 0, Nothing, IntPtr.Zero) + ' start the channel playing & encoding + Bass.BASS_ChannelPlay(channel, False) + + Start writing a channel to a WAV file (output.wav): + + BassEnc.BASS_Encode_Start(channel, "output.wav", + BASSEncode.BASS_ENCODE_PCM, null, IntPtr.Zero); + // start the channel playing & encoding + Bass.BASS_ChannelPlay(channel, false); + + + BassEnc.BASS_Encode_Start(channel, "output.wav", + BASSEncode.BASS_ENCODE_PCM, Nothing, IntPtr.Zero) + ' start the channel playing & encoding + Bass.BASS_ChannelPlay(channel, False) + + + + + + Sends a RIFF chunk to an encoder. + + The encoder handle... a HENCODE. + The 4 character chunk id (e.g. 'bext'). + The pointer to the buffer containing the chunk data (without the id). + The number of bytes in the buffer. + If successful, is returned, else is returned. Use to get the error code. + + BASSenc writes the minimum chunks required of a WAV file: "fmt" and "data", and "ds64" and "fact" when appropriate. This function can be used to add other chunks. + For example, a BWF "bext" chunk or "INFO" tags. + Chunks can only be added prior to sample data being sent to the encoder. The BASS_ENCODE_PAUSE flag can be used when starting the encoder to ensure that no sample data is sent before additional chunks have been set. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILNo RIFF headers/chunks are being sent to the encoder (due to the BASS_ENCODE_NOHEAD flag being in effect), or sample data encoding has started. + BASS_ERROR_ENDEDThe encoder has died. + + + + + + + Sends a RIFF chunk to an encoder. + + The encoder handle... a HENCODE. + The 4 character chunk id (e.g. 'bext'). + The buffer containing the chunk data (without the id). + The number of bytes in the buffer. + If successful, is returned, else is returned. Use to get the error code. + BASSenc writes the minimum chunks required of a WAV file: "fmt" and "data", and "ds64" and "fact" when appropriate. This function can be used to add other chunks. + For example, a BWF "bext" chunk or "INFO" tags. + Chunks can only be added prior to sample data being sent to the encoder. The BASS_ENCODE_PAUSE flag can be used when starting the encoder to ensure that no sample data is sent before additional chunks have been set. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILNo RIFF headers/chunks are being sent to the encoder (due to the BASS_ENCODE_NOHEAD flag being in effect), or sample data encoding has started. + BASS_ERROR_ENDEDThe encoder has died. + + + + + Adding a BEXT chunk: + + BASS_TAG_BEXT bext = new BASS_TAG_BEXT(); + ... set the bext member here + string codingHistory = "..."; + byte[] bextData = bext.AsByteArray(codingHistory); + bool ok = BassEnc.BASS_Encode_AddChunk(handle, "bext", bextData, bextData.Length); + + + + + + Checks if an encoder is running on a channel. + + The encoder or channel handle... a HENCODE, HSTREAM, HMUSIC, or HRECORD. + The return value is one of the folowing (see ): + + BASS_ACTIVE_STOPPEDNo encoder is running on the channel. + BASS_ACTIVE_PLAYINGThere is an encoder running on the channel. + BASS_ACTIVE_PAUSEDThere is an encoder running on the channel, but it is paused. + + + + When checking if there's an encoder running on a channel, and there are multiple encoders on the channel, BASS_ACTIVE_PLAYING will be returned if any of them are active. + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + In a recording callback (see ) this might be used to check, if recording should be continued: + + private bool RecordingCallback(int channel, IntPtr buffer, int length, IntPtr user) + { + // continue recording if encoder is alive + return ( BassEnc.BASS_Encode_IsActive(channel) != BASSActive.BASS_ACTIVE_STOPPED ); + } + + + Private Function RecordingCallback(channel As Integer, buffer As IntPtr, + length As Integer, user As IntPtr) As Boolean + ' continue recording if encoder is alive + Return BassEnc.BASS_Encode_IsActive(channel) <> BASSActive.BASS_ACTIVE_STOPPED + End Function + + + + + + Stops encoding on a channel. + + The encoder or channel handle... a HENCODE, HSTREAM, HMUSIC, or HRECORD. + If successful, is returned, else is returned. Use to get the error code. + + This function will free an encoder immediately, without waiting for any data that may be remaining in the queue. can be used to have an encoder process the queue before it is freed. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + + Stops async encoding on a channel. + + The encoder or channel handle... a HENCODE, HSTREAM, HMUSIC, or HRECORD. + Process the queue first? If so, the encoder will not be freed until after any data remaining in the queue has been processed, and it will not accept any new data in the meantime. + If successful, is returned, else is returned. Use to get the error code. + + When an encoder is told to wait for its queue to be processed, this function will return immediately and the encoder will be freed in the background after the queued data has been processed. + can be used to request notification of when the encoder has been freed. (or this function with queue = ) can be used to cancel to queue processing and free the encoder immediately. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + + Pauses or resumes encoding on a channel. + + The encoder or channel handle... a HENCODE, HSTREAM, HMUSIC, or HRECORD. + Paused? + If no encoder has been started on the channel, is returned, otherwise is returned. + If successful, is returned, else is returned. Use to get the error code. + + When an encoder is paused, no sample data will be sent to the encoder "automatically". Data can still be sent to the encoder "manually" though, via the function. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + + Sends sample data to the encoder. + + The encoder or channel handle... a HENCODE, HSTREAM, HMUSIC, or HRECORD. + A pointer to the buffer containing the sample data. + The number of BYTES in the buffer. + If successful, is returned, else is returned. Use to get the error code. + There's usually no need to use this function, as the channel's sample data will automatically be fed to the encoder. But in some situations, it could be useful to be able to manually feed the encoder instead. + The sample data is expected to be the same format as the channel's, or floating-point if the BASS_CONFIG_FLOATDSP (see ) option is enabled. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ENDEDThe encoder has died. + + + + + + + Sends sample data to the encoder. + This overload uses a managed float[] to handover sample data to the encoder (typically not used, since most encoders expect 16-bit, so use the int[] or short[] overload). + + The encoder or channel handle... a HENCODE, HSTREAM, HMUSIC, or HRECORD. + A reference to the first array element (float[0]) containing the sample data. + The number of BYTES in the buffer. + If successful, is returned, else is returned. Use to get the error code. + There's usually no need to use this function, as the channel's sample data will automatically be fed to the encoder. But in some situations, it could be useful to be able to manually feed the encoder instead. + The sample data is expected to be the same format as the channel's, or floating-point if the BASS_CONFIG_FLOATDSP (see ) option is enabled. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ENDEDThe encoder has died. + + + + + + + Sends sample data to the encoder. + This overload uses a managed int[] to handover sample data to the encoder (Note: An int[] is 32-bit. When using 16-bit samples we can keep a stereo pair in here). + + The encoder or channel handle... a HENCODE, HSTREAM, HMUSIC, or HRECORD. + A reference to the first array element (int[0]) containing the sample data. + The number of BYTES in the buffer. + If successful, is returned, else is returned. Use to get the error code. + There's usually no need to use this function, as the channel's sample data will automatically be fed to the encoder. But in some situations, it could be useful to be able to manually feed the encoder instead. + The sample data is expected to be the same format as the channel's, or floating-point if the BASS_CONFIG_FLOATDSP (see ) option is enabled. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ENDEDThe encoder has died. + + + + + + + Sends sample data to the encoder. + This overload uses a managed short[] to handover sample data to the encoder (perfect for 16-bit samples). + + The encoder or channel handle... a HENCODE, HSTREAM, HMUSIC, or HRECORD. + A reference to the first array element (short[0]) containing the sample data. + The number of BYTES in the buffer. + If successful, is returned, else is returned. Use to get the error code. + There's usually no need to use this function, as the channel's sample data will automatically be fed to the encoder. But in some situations, it could be useful to be able to manually feed the encoder instead. + The sample data is expected to be the same format as the channel's, or floating-point if the BASS_CONFIG_FLOATDSP (see ) option is enabled. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ENDEDThe encoder has died. + + + + + + + Sends sample data to the encoder. + This overload uses a managed byte[] to handover sample data to the encoder (perfect for 8-bit samples). + + The encoder or channel handle... a HENCODE, HSTREAM, HMUSIC, or HRECORD. + A reference to the first array element (byte[0]) containing the sample data. + The number of BYTES in the buffer. + If successful, is returned, else is returned. Use to get the error code. + There's usually no need to use this function, as the channel's sample data will automatically be fed to the encoder. But in some situations, it could be useful to be able to manually feed the encoder instead. + The sample data is expected to be the same format as the channel's, or floating-point if the BASS_CONFIG_FLOATDSP (see ) option is enabled. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ENDEDThe encoder has died. + + + + + + + Retrieves the amount data sent to or received from an encoder, or sent to a cast server. + + The encoder handle. + The count to retrieve. One of the following (see ): + + BASS_ENCODE_COUNT_INData sent to the encoder. + BASS_ENCODE_COUNT_OUTData received from the encoder. This only applies when the encoder outputs to STDOUT or it is an ACM encoder. + BASS_ENCODE_COUNT_CASTData sent to a cast server. + BASS_ENCODE_COUNT_QUEUEData currently in the queue, waiting to be sent to the encoder, if async encoding is enabled (i.e. the flag was used with ). + BASS_ENCODE_COUNT_QUEUE_LIMITThe queue's size limit. + BASS_ENCODE_COUNT_QUEUE_FAILData not queued due to the queue being full or out of memory. + + + If successful, the requested count (in bytes) is returned, else -1 is returned. Use to get the error code. + + The queue counts are based on the channel's sample format (floating-point if the BASS_CONFIG_FLOATDSP option is enabled), while the BASS_ENCODE_COUNT_IN count is based on the sample format used by the encoder, which could be different if one of the BASS_ENCODE_FP flags is active or the encoder is using an ACM codec (which take 16-bit data). + When the encoder output is being sent to a cast server, the BASS_ENCODE_COUNT_CAST count will match the BASS_ENCODE_COUNT_OUT count, unless there have been problems (eg. network timeout) that have caused data to be dropped. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ILLPARAM is not valid. + + + + + + + + + + + + + + + + + + Presents the user with a list of available ACM (Audio Compression Manager) codec output formats to choose from. + The overload implements the Unicode version for the title, so the BASS_UNICODE flag will be added automatically. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + Pointer to the format buffer. + Size of the format buffer. If this is 0, then a suggested format buffer length is returned (which is the maximum length of all installed codecs), without displaying the codec selector. + Window title for the selector... = "Choose the output format". + A combination of these flags : + + BASS_ACM_DEFAULTUse the format buffer (form) contents as the default choice in the codec selector. + BASS_ACM_RATEOnly include formats with the same sample rate as the source. + BASS_ACM_CHANSOnly include formats with the same number of channels (mono/stereo) as the source. + BASS_ACM_SUGGESTSuggest a format without letting the user choose. The wanted format tag (eg. WAVE_FORMAT_ADPCM) should be specified in the HIWORD. + + The HighWord - use (flags,format) - can be used to restrict the choice to a particular format tag (eg. WAVE_FORMAT_ADPCM). This is required with BASS_ACM_SUGGEST, and is optional otherwise. + See for a list of typical formats being used. + + If successful, the user-selected codec format details are put in the provided buffer and the length of the format details is returned, else 0 is returned. + Use to get the error code. If formlen is 0, then the suggested format buffer size is returned. + This function presents the user with a list of available ACM codecs to choose from, given the sample format of the channel. The details of the chosen codec's output are returned in the form buffer, + which can then be used with or to begin encoding. + The buffer contents are actually a or structure. + If writing the encoder output to a WAVE file, the form buffer contents would be the format chunk ("fmt") of the file. + To not let the user choose a codec, but automatically suggest a codec you might also use the method. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThere are no codecs available that will accept the channel's format. + BASS_ERROR_ACM_CANCELThe user pressed the "cancel" button. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Let the user choose a codec, and setup an encoder on a channel using the chosen codec: + + // get suggested (maximum) format buffer size + int formlen = BassEnc.BASS_Encode_GetACMFormat(0, IntPtr.Zero, 0, null, BASSACMFormat.BASS_ACM_NONE); + // create a buffer for the codec + byte[] buffer = new byte[formlen]; + // now create a pinned handle, so that the Garbage Collector will not move this object + GCHandle hGC = GCHandle.Alloc( buffer, GCHandleType.Pinned ); + // get the pointer to that pinned object + IntPtr codec = hGC.AddrOfPinnedObject(); + // let the user choose a codec... + if ( BassEnc.BASS_Encode_GetACMFormat( channel, codec, formlen, "Choose your format", BASSACMFormat.BASS_ACM_DEFAULT) > 0 ) + { + // get the generic codec information back + ACMFORMAT acm = (ACMFORMAT)Marshal.PtrToStructure(codec, typeof(ACMFORMAT)); + // begin encoding using the codec + BassEnc.BASS_Encode_StartACMFile( channel, codec, BASSEncode.BASS_ENCODE_DEFAULT, "acm.wav"); + } + // free the codec format buffer (you might free it even if encoding is still running) + hGC.Free(); + + + ' get suggested (maximum) format buffer size + Dim formlen As Integer = BassEnc.BASS_Encode_GetACMFormat(0, IntPtr.Zero, 0, Nothing, BASSACMFormat.BASS_ACM_NONE) + ' create a buffer for the codec + Dim buffer(formlen - 1) As Byte + ' now create a pinned handle, so that the Garbage Collector will not move this object + Dim hGC As GCHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned) + ' get the pointer to that pinned object + Dim codec As IntPtr = hGC.AddrOfPinnedObject() + ' let the user choose a codec... + If BassEnc.BASS_Encode_GetACMFormat(channel, codec, formlen, "Choose your format", + BASSACMFormat.BASS_ACM_DEFAULT) > 0 Then + ' get the generic codec information back + Dim acm As ACMFORMAT = CType(Marshal.PtrToStructure(codec, GetType(ACMFORMAT)), ACMFORMAT) + ' begin encoding using the codec + BassEnc.BASS_Encode_StartACMFile(channel, codec, BASSEncode.BASS_ENCODE_DEFAULT, "acm.wav") + End If + ' free the codec format buffer (you might free it even if encoding is still running) + hGC.Free() + + If you are into C# using native pointers in an unsafe codeblock would be even faster: + + // get suggested (maximum) format buffer size + int formlen = BassEnc.BASS_Encode_GetACMFormat(0, IntPtr.Zero, 0, null, BASSACMFormat.BASS_ACM_NONE); + // create a buffer for the codec + byte[] buffer = new byte[formlen]; + unsafe + { + fixed (byte* p = buffer) + { + // let the user choose a codec... + if ( BassEnc.BASS_Encode_GetACMFormat( channel, (IntPtr)p, formlen, "Choose your format", BASSACMFormat.BASS_ACM_DEFAULT) > 0 ) + { + // get the generic codec information back + ACMFORMAT acm = (ACMFORMAT)Marshal.PtrToStructure((IntPtr)p, typeof(ACMFORMAT)); + // begin encoding using the codec + BassEnc.BASS_Encode_StartACMFile( channel, acm, BASSEncode.BASS_ENCODE_DEFAULT, "acm.wav"); + } + } + } + + For more convenience use the other overload of . + + + + + Presents the user with a list of available ACM (Audio Compression Manager) codec output formats to choose from. + This overload returns the generic codec format and handles all the rest already for you. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + Window title for the selector... = "Choose the output format". + A combination of these flags : + + BASS_ACM_DEFAULTUse the format buffer (form) contents as the default choice in the codec selector. + BASS_ACM_RATEOnly include formats with the same sample rate as the source. + BASS_ACM_CHANSOnly include formats with the same number of channels (mono/stereo) as the source. + BASS_ACM_SUGGESTSuggest a format without letting the user choose. The wanted format tag (eg. WAVE_FORMAT_ADPCM) should be specified in the HIWORD. + + The HighWord - use (flags,format) - can be used to restrict the choice to a particular format tag (eg. WAVE_FORMAT_ADPCM). This is required with BASS_ACM_SUGGEST, and is optional otherwise. + See for a list of typical formats being used. + + The wanted codec format (use one of the flags, or see the MMREG.H file for more). + If successful, an instance of the generic codec format is returned, else is returned. Use to get the error code. + This function presents the user with a list of available ACM codecs to choose from, given the sample format of the channel. The details of the chosen codec's output are returned as a generic codec format , + which can then be used with or to begin encoding. + If writing the encoder output to a WAVE file, the codec format's contents would be the format chunk ("fmt") of the file. + To not let the user choose a codec, but automatically suggest a codec you might also use the method. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThere are no codecs available that will accept the channel's format. + BASS_ERROR_ACM_CANCELThe user pressed the "cancel" button. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Let the user choose a codec, and setup an encoder on a channel using the chosen codec: + + ACMFORMAT codec = BassEnc.BASS_Encode_GetACMFormat(channel, "Select your encoder", + BASSACMFormat.BASS_ACM_DEFAULT, + WAVEFormatTag.UNKNOWN); + if ( codec != null ) + { + // begin encoding using the codec + BassEnc.BASS_Encode_StartACMFile( channel, codec, BASSEncode.BASS_ENCODE_DEFAULT, "acm.wav"); + } + + + Dim codec As ACMFORMAT = BassEnc.BASS_Encode_GetACMFormat(channel, "Select your encoder", + BASSACMFormat.BASS_ACM_DEFAULT, + WAVEFormatTag.UNKNOWN) + If Not (codec Is Nothing) Then + ' begin encoding using the codec + BassEnc.BASS_Encode_StartACMFile(channel, codec, BASSEncode.BASS_ENCODE_DEFAULT, "acm.wav") + End If + + + + + + Presents the user with a list of available ACM (Audio Compression Manager) codec output formats to choose from. + This overload returns the generic codec format in the and handles all the rest already for you. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + The to preselect. Will return the newly selected codec. + Window title for the selector... = "Choose the output format". + A combination of these flags : + + BASS_ACM_DEFAULTUse the format buffer (form) contents as the default choice in the codec selector. + BASS_ACM_RATEOnly include formats with the same sample rate as the source. + BASS_ACM_CHANSOnly include formats with the same number of channels (mono/stereo) as the source. + BASS_ACM_SUGGESTSuggest a format without letting the user choose. The wanted format tag (eg. WAVE_FORMAT_ADPCM) should be specified in the HIWORD. + + The HighWord - use (flags,format) - can be used to restrict the choice to a particular format tag (eg. WAVE_FORMAT_ADPCM). This is required with BASS_ACM_SUGGEST, and is optional otherwise. + See for a list of typical formats being used. + + If successful, is returned and will contain the selected ACM format codec - else is returned. Use to get the error code. + This function presents the user with a list of available ACM codecs to choose from, given the sample format of the channel. The details of the chosen codec's output are returned as a generic codec format , + which can then be used with or to begin encoding. + If writing the encoder output to a WAVE file, the codec format's contents would be the format chunk ("fmt") of the file. + To not let the user choose a codec, but automatically suggest a codec you might also use the method. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThere are no codecs available that will accept the channel's format. + BASS_ERROR_ACM_CANCELThe user pressed the "cancel" button. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Returns a suggested ACM (Audio Compression Manager) codec output format without displaying a user dialog. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + A combination of these flags : + + BASS_ACM_DEFAULTUse the format buffer (form) contents as the default choice in the codec selector. + BASS_ACM_RATEOnly include formats with the same sample rate as the source. + BASS_ACM_CHANSOnly include formats with the same number of channels (mono/stereo) as the source. + BASS_ACM_SUGGESTThis flag will be added automatically. + + + The wanted codec format (use one of the flags, or see the MMREG.H file for more). + If successful, an instance of the generic codec format is returned, else is returned. Use to get the error code. + This function does NOT presents the user with a list of available ACM codecs to choose from, instead an automatic suggested codec will be returned, which matches the given format. + The details of the chosen codec's output are returned as a generic codec format , + which can then be used with or to begin encoding. + If writing the encoder output to a WAVE file, the codec format's contents would be the format chunk ("fmt") of the file. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThere are no codecs available that will accept the channel's format. + BASS_ERROR_ACM_CANCELThe user pressed the "cancel" button. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Without letting the user choose, setup an MP3 encoder on a channel: + + ACMFORMAT codec = BassEnc.BASS_Encode_GetACMFormatSuggest(channel, + BASSACMFormat.BASS_ACM_CHANS | BASSACMFormat.BASS_ACM_RATE, + WAVEFormatTag.MPEGLAYER3); + if ( codec != null ) + { + // begin encoding using the codec + BassEnc.BASS_Encode_StartACMFile( channel, codec, BASSEncode.BASS_ENCODE_DEFAULT, "acm.mp3"); + } + + + Dim codec As ACMFORMAT = BassEnc.BASS_Encode_GetACMFormatSuggest(channel, + BASSACMFormat.BASS_ACM_CHANS Or BASSACMFormat.BASS_ACM_RATE, + WAVEFormatTag.MPEGLAYER3) + If Not (codec Is Nothing) Then + ' begin encoding using the codec + BassEnc.BASS_Encode_StartACMFile(channel, codec, BASSEncode.BASS_ENCODE_DEFAULT, "acm.mp3") + End If + + + + + + Sets up an encoder on a channel, using an ACM codec and sending the output to a user defined function. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + ACM codec output format (an instance as returned by ). + A combination of these flags : + + BASS_ENCODE_PAUSEStart the encoder paused. + BASS_ENCODE_AUTOFREEAutomatically free the encoder when the source channel is freed. + BASS_ENCODE_QUEUEQueue data to feed the encoder asynchronously. This prevents the data source (DSP system or call) getting blocked by the encoder, but if data is queud more quickly than the encoder can process it, that could result in lost data. + BASS_ENCODE_CAST_NOLIMITDon't limit the data rate (to real-time speed) when sending to a Shoutcast or Icecast server. + BASS_ENCODE_LIMITLimit the data rate to real-time speed, by introducing a delay when the rate is too high. With BASS 2.4.6 or above, this flag is ignored when the encoder is fed in a playback buffer update cycle (including and calls), to avoid possibly causing playback buffer underruns. Except for in those instances, this flag is applied automatically when the encoder is feeding a Shoutcast or Icecast server. + + + Callback function to receive the encoded data. + User instance data to pass to the callback function. + The encoder handle is returned if the encoder is successfully started, else 0 is returned. Use to get the error code. + The ACM encoder allows installed ACM (Audio Compression Manager) codecs to be used for encoding. The codec used is determined by the contents of the form parameter. + The function can be used to initialize that. + Internally, the sending of sample data to the encoder is implemented via a DSP callback on the channel. That means when you play the channel (or call if it's a decoding channel), the sample data will be sent to the encoder at the same time. + The encoding is performed in the DSP callback. There isn't a separate process doing the encoding, as when using an external encoder via . + By default, the encoder DSP has a priority setting of -1000, which determines where in the DSP chain the encoding is performed. That can be changed using the BASS_CONFIG_ENCODE_PRIORITY config option (see ). + Besides the automatic DSP system, data can also be manually fed to the encoder via the function. Both methods can be used together, but in general, the "automatic" system ought be paused when using the "manual" system, by use of the BASS_ENCODE_PAUSE flag or the function. + When queued encoding is enabled via the BASS_ENCODE_QUEUE flag, the DSP system or call will just buffer the data, and the data will then be fed to the encoder by another thread. The buffer will grow as needed to hold the queued data, up to a limit specified by the BASS_CONFIG_ENCODE_QUEUE config option. + If the limit is exceeded (or there is no free memory), data will be lost; can be used to be notified of that occurrence. The amount of data that is currently queued, as well as the queue limit and how much data has been lost, is available from . + When done encoding, use to close the encoder. + Multiple encoders can be set on a channel. For simplicity, the encoder functions will accept either an encoder handle or a channel handle. When using a channel handle, the function is applied to all encoders that are set on that channel. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe codec specified in couldn't be initialized. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Setup an ACM encoder with a callback to process the encoded data: + + // the encoding callback + private ENCODEPROC _myEncProc; + private byte[] _encbuffer = null; + ... + ACMFORMAT codec = BassEnc.BASS_Encode_GetACMFormat(channel, "Select your encoder", + BASSACMFormat.BASS_ACM_DEFAULT, WAVEFormatTag.UNKNOWN); + if ( codec != null ) + { + // create the delegate + _myEncProc = new ENCODEPROC(MyEncoderProc); + // begin encoding using the codec with the delegate callback + int encHandle = BassEnc.BASS_Encode_StartACM( channel, codec, + BASSEncode.BASS_ENCODE_DEFAULT, _myEncProc, IntPtr.Zero); + } + ... + private bool MyEncodingWriter(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + // dynamic buffer allocation + if ( _encbuffer == null || _encbuffer.Length < length ) + _encbuffer = new byte[length]; + + // copy from managed to unmanaged memory + Marshal.Copy(buffer, _encbuffer, 0, length); + // process the data in _encbuffer, e.g. write to disk or whatever + ... + } + + + Private _myEncProc As ENCODEPROC + Private _encbuffer As Byte() = Nothing + ... + Dim codec As ACMFORMAT = BassEnc.BASS_Encode_GetACMFormat(channel, "Select your encoder", + BASSACMFormat.BASS_ACM_DEFAULT, WAVEFormatTag.UNKNOWN) + If Not (codec Is Nothing) Then + ' create the delegate + _myEncProc = New ENCODEPROC(AddressOf MyEncoderProc) + ' begin encoding using the codec with the delegate callback + Dim encHandle As Integer = BassEnc.BASS_Encode_StartACM(channel, codec, + BASSEncode.BASS_ENCODE_DEFAULT, _myEncProc, IntPtr.Zero) + End If + ... + Private Function MyEncodingWriter(handle As Integer, channel As Integer, + buffer As IntPtr, length As Integer, user As IntPtr) As Boolean + ' dynamic buffer allocation + If _encbuffer Is Nothing OrElse _encbuffer.Length < length Then + _encbuffer = New Byte(length) {} + End If + + ' copy from managed to unmanaged memory + Marshal.Copy(buffer, _encbuffer, 0, length) + ' process the data in _encbuffer, e.g. write to disk or whatever + ... + End Function + + If you are into C# you might also use native pointer access in an unsafe codeblock: + + private unsafe void MyEncoding(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + // here we receive the encoded data back. + // the encoded data is a kind of raw byte buffer... + byte *data = (byte*)buffer; + + for (int a=0; a<length; a++) + { + // do whatever you want with the encoded data + _stream.WriteByte( data[a] ); + } + } + + + + + + Sets up an encoder on a channel, using an ACM codec and sending the output to a user defined function. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + ACM codec output format (buffer as returned by ). + A combination of these flags : + + BASS_ENCODE_PAUSEStart the encoder paused. + BASS_ENCODE_AUTOFREEAutomatically free the encoder when the source channel is freed. + BASS_ENCODE_QUEUEQueue data to feed the encoder asynchronously. This prevents the data source (DSP system or call) getting blocked by the encoder, but if data is queud more quickly than the encoder can process it, that could result in lost data. + BASS_ENCODE_CAST_NOLIMITDon't limit the data rate (to real-time speed) when sending to a Shoutcast or Icecast server. + BASS_ENCODE_LIMITLimit the data rate to real-time speed, by introducing a delay when the rate is too high. With BASS 2.4.6 or above, this flag is ignored when the encoder is fed in a playback buffer update cycle (including and calls), to avoid possibly causing playback buffer underruns. Except for in those instances, this flag is applied automatically when the encoder is feeding a Shoutcast or Icecast server. + + + Callback function to receive the encoded data. + User instance data to pass to the callback function. + The encoder handle is returned if the encoder is successfully started, else 0 is returned. Use to get the error code. + The ACM encoder allows installed ACM (Audio Compression Manager) codecs to be used for encoding. The codec used is determined by the contents of the form parameter. + The function can be used to initialize that. + Internally, the sending of sample data to the encoder is implemented via a DSP callback on the channel. That means when you play the channel (or call if it's a decoding channel), the sample data will be sent to the encoder at the same time. + The encoding is performed in the DSP callback. There isn't a separate process doing the encoding, as when using an external encoder via . + By default, the encoder DSP has a priority setting of -1000, which determines where in the DSP chain the encoding is performed. That can be changed using the BASS_CONFIG_ENCODE_PRIORITY config option (see ). + Besides the automatic DSP system, data can also be manually fed to the encoder via the function. Both methods can be used together, but in general, the "automatic" system ought be paused when using the "manual" system, by use of the BASS_ENCODE_PAUSE flag or the function. + When done encoding, use to close the encoder. + Multiple encoders can be set on a channel. For simplicity, the encoder functions will accept either an encoder handle or a channel handle. When using a channel handle, the function is applied to all encoders that are set on that channel. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe codec specified in couldn't be initialized. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Setup an ACM encoder with a callback to process the encoded data: + + // get suggested (maximum) format buffer size + int formlen = BassEnc.BASS_Encode_GetACMFormat(0, IntPtr.Zero, 0, null, BASSACMFormat.BASS_ACM_NONE); + // create a buffer for the codec + byte[] buffer = new byte[formlen]; + unsafe + { + fixed (byte* p = buffer) + { + // let the user choose a codec... + if ( BassEnc.BASS_Encode_GetACMFormat( channel, (IntPtr)p, formlen, "Choose your format", + BASSACMFormat.BASS_ACM_DEFAULT) > 0 ) + { + // create the delegate + _myEncProc = new ENCODEPROC(MyEncoderProc); + // begin encoding using the codec with the delegate callback + int encHandle = BassEnc.BASS_Encode_StartACMFile(channel, (IntPtr)p, BASSEncode.BASS_ENCODE_DEFAULT, _myEncProc, IntPtr.Zero); + } + } + } + ... + // the encoding callback + private ENCODEPROC _myEncProc; // keep the callback delegate in a global member + private bool MyEncodingWriter(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + ... + } + + + ' get suggested (maximum) format buffer size + Dim formlen As Integer = BassEnc.BASS_Encode_GetACMFormat(0, IntPtr.Zero, 0, Nothing, BASSACMFormat.BASS_ACM_NONE) + ' create a buffer for the codec + Dim buffer(formlen - 1) As Byte + ' now create a pinned handle, so that the Garbage Collector will not move this object + Dim hGC As GCHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned) + ' get the pointer to that pinned object + Dim codec As IntPtr = hGC.AddrOfPinnedObject() + ' let the user choose a codec... + If BassEnc.BASS_Encode_GetACMFormat(channel, codec, formlen, "Choose your format", + BASSACMFormat.BASS_ACM_DEFAULT) > 0 Then + ' create the delegate + _myEncProc = New ENCODEPROC(AddressOf MyEncoderProc) + ' begin encoding using the codec with the delegate callback + Dim encHandle As Integer = BassEnc.BASS_Encode_StartACMFile(channel, codec, + BASSEncode.BASS_ENCODE_DEFAULT, _myEncProc, IntPtr.Zero) + End If + ' free the codec format buffer (you might free it even if encoding is still running) + hGC.Free() + ... + Private _myEncProc As ENCODEPROC + Private Function MyEncodingWriter(handle As Integer, channel As Integer, + buffer As IntPtr, length As Integer, user As IntPtr) As Boolean + ... + End Function + + If you are into C# using native pointers in an unsafe codeblock would be even faster: + + + + + + + + + + + + + + + + + + + + + + + + + Sets up an encoder on a channel, using an ACM codec and writing the output to a file. + This overload represents the Unicode version for the file name. The BASS_UNICODE flag will automatically be added if missing. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + ACM codec output format (buffer as returned by ). + A combination of these flags : + + BASS_ENCODE_NOHEADDon't write a WAVE header to the file. + BASS_ENCODE_RF64Write an RF64 header instead of a standard RIFF header, allowing the file to go beyond 4GB in size. This flag is ignored if the BASS_ENCODE_NOHEAD flag is used. + BASS_ENCODE_QUEUEQueue data to feed the encoder asynchronously. This prevents the data source (DSP system or call) getting blocked by the encoder, but if data is queud more quickly than the encoder can process it, that could result in lost data. + BASS_ENCODE_PAUSEStart the encoder paused. + BASS_ENCODE_AUTOFREEAutomatically free the encoder when the source channel is freed. + + + The filename to write. + The encoder handle is returned if the encoder is successfully started, else 0 is returned. Use to get the error code. + The ACM encoder allows installed ACM (Audio Compression Manager) codecs to be used for encoding. The codec used is determined by the contents of the form parameter. The function can be used to initialize that. + Unless the BASS_ENCODE_NOHEAD flag is specified, a WAVE header and the contents will be written to the file. This is generally required for the file to be playable, but in some cases (eg. MP3) it's not. + Standard RIFF WAV files are limited to a little over 4GB in size, so BASSenc will automatically stop encoding at that point. That size limit can be overcome with an RF64 file. When writing an RF64 WAV file, a standard RIFF header will still be written initially, which will only be replaced by an RF64 header at the end if the file size has exceeded the standard limit. + Internally, the sending of sample data to the encoder is implemented via a DSP callback on the channel. That means when you play the channel (or call if it's a decoding channel), the sample data will be sent to the encoder at the same time. + The encoding is performed in the DSP callback. There isn't a separate process doing the encoding, as when using an external encoder via . + By default, the encoder DSP has a priority setting of -1000, which determines where in the DSP chain the encoding is performed. That can be changed using the BASS_CONFIG_ENCODE_PRIORITY config option (see ). + Besides the automatic DSP system, data can also be manually fed to the encoder via the function. Both methods can be used together, but in general, the "automatic" system ought be paused when using the "manual" system, by use of the BASS_ENCODE_PAUSE flag or the function. + When done encoding, use to close the encoder. + Multiple encoders can be set on a channel. For simplicity, the encoder functions will accept either an encoder handle or a channel handle. When using a channel handle, the function is applied to all encoders that are set on that channel. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe codec specified in couldn't be initialized. + BASS_ERROR_CREATEThe file couldn't be created. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Setup an ACM encoder with a callback to process the encoded data: + + // get suggested (maximum) format buffer size + int formlen = BassEnc.BASS_Encode_GetACMFormat(0, IntPtr.Zero, 0, null, BASSACMFormat.BASS_ACM_NONE); + // create a buffer for the codec + byte[] form = new byte[formlen]; + unsafe + { + fixed (byte* p = form) + { + // automatically suggest an MP3 codec + if (BassEnc.BASS_Encode_GetACMFormat(handle, (IntPtr)p, formlen, null, + (BASSACMFormat)Utils.MakeLong((int)(BASSACMFormat.BASS_ACM_SUGGEST | BASSACMFormat.BASS_ACM_RATE | BASSACMFormat.BASS_ACM_CHANS), + (int)WAVEFormatTag.MPEGLAYER3)) > 0) + { + // begin encoding + int encHandle = BassEnc.BASS_Encode_StartACMFile(channel, (IntPtr)p, + BASSEncode.BASS_ENCODE_NOHEAD, "output.mp3" ); + } + + + ' get suggested (maximum) format buffer size + Dim formlen As Integer = BassEnc.BASS_Encode_GetACMFormat(0, IntPtr.Zero, 0, Nothing, BASSACMFormat.BASS_ACM_NONE) + ' create a buffer for the codec + Dim buffer(formlen - 1) As Byte + ' now create a pinned handle, so that the Garbage Collector will not move this object + Dim hGC As GCHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned) + ' get the pointer to that pinned object + Dim codec As IntPtr = hGC.AddrOfPinnedObject() + ' automatically suggest an MP3 codec + If BassEnc.BASS_Encode_GetACMFormat(handle, codec, formlen, Nothing, + CType(Utils.MakeLong(CInt(BASSACMFormat.BASS_ACM_SUGGEST Or BASSACMFormat.BASS_ACM_RATE Or BASSACMFormat.BASS_ACM_CHANS), + CInt(WAVEFormatTag.MPEGLAYER3)), BASSACMFormat)) > 0 Then + ' begin encoding + Dim encHandle As Integer = BassEnc.BASS_Encode_StartACMFile(channel, codec, + BASSEncode.BASS_ENCODE_NOHEAD, "output.mp3") + End If + ' free the codec format buffer (you might free it even if encoding is still running) + hGC.Free() + + + + + + Sets up an encoder on a channel, using an ACM codec and writing the output to a file. + This overload represents the Unicode version for the file name. The BASS_UNICODE flag will automatically be added if missing. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + ACM codec output format (buffer as returned by ). + A combination of these flags : + + BASS_ENCODE_NOHEADDon't write a WAVE header to the file. + BASS_ENCODE_RF64Write an RF64 header instead of a standard RIFF header, allowing the file to go beyond 4GB in size. This flag is ignored if the BASS_ENCODE_NOHEAD flag is used. + BASS_ENCODE_QUEUEQueue data to feed the encoder asynchronously. This prevents the data source (DSP system or call) getting blocked by the encoder, but if data is queud more quickly than the encoder can process it, that could result in lost data. + BASS_ENCODE_PAUSEStart the encoder paused. + BASS_ENCODE_AUTOFREEAutomatically free the encoder when the source channel is freed. + + + The filename to write. + The encoder handle is returned if the encoder is successfully started, else 0 is returned. Use to get the error code. + The ACM encoder allows installed ACM (Audio Compression Manager) codecs to be used for encoding. The codec used is determined by the contents of the form parameter. The function can be used to initialize that. + Unless the BASS_ENCODE_NOHEAD flag is specified, a WAVE header and the contents will be written to the file. This is generally required for the file to be playable, but in some cases (eg. MP3) it's not. + Standard RIFF WAV files are limited to a little over 4GB in size, so BASSenc will automatically stop encoding at that point. That size limit can be overcome with an RF64 file. When writing an RF64 WAV file, a standard RIFF header will still be written initially, which will only be replaced by an RF64 header at the end if the file size has exceeded the standard limit. + Internally, the sending of sample data to the encoder is implemented via a DSP callback on the channel. That means when you play the channel (or call if it's a decoding channel), the sample data will be sent to the encoder at the same time. + The encoding is performed in the DSP callback. There isn't a separate process doing the encoding, as when using an external encoder via . + By default, the encoder DSP has a priority setting of -1000, which determines where in the DSP chain the encoding is performed. That can be changed using the BASS_CONFIG_ENCODE_PRIORITY config option (see ). + Besides the automatic DSP system, data can also be manually fed to the encoder via the function. Both methods can be used together, but in general, the "automatic" system ought be paused when using the "manual" system, by use of the BASS_ENCODE_PAUSE flag or the function. + When done encoding, use to close the encoder. + Multiple encoders can be set on a channel. For simplicity, the encoder functions will accept either an encoder handle or a channel handle. When using a channel handle, the function is applied to all encoders that are set on that channel. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe codec specified in couldn't be initialized. + BASS_ERROR_CREATEThe file couldn't be created. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Setup an ACM encoder with a callback to process the encoded data: + + ACMFORMAT codec = BassEnc.BASS_Encode_GetACMFormat(channel, "Select your encoder", + BASSACMFormat.BASS_ACM_DEFAULT, WAVEFormatTag.UNKNOWN); + if ( codec != null ) + { + // begin encoding + int encHandle = BassEnc.BASS_Encode_StartACMFile( channel, codec, + BASSEncode.BASS_ENCODE_DEFAULT, "output.wav" ); + } + + + Dim codec As ACMFORMAT = BassEnc.BASS_Encode_GetACMFormat(channel, "Select your encoder", + BASSACMFormat.BASS_ACM_DEFAULT, WAVEFormatTag.UNKNOWN) + If Not (codec Is Nothing) Then + ' begin encoding + Dim encHandle As Integer = BassEnc.BASS_Encode_StartACMFile(channel, codec, + BASSEncode.BASS_ENCODE_DEFAULT, "output.wav") + End If + + + + + + Sets a callback function on an encoder (or all encoders on a channel) to receive notifications about its status. + + The encoder or channel handle... a HENCODE, HSTREAM, HMUSIC, or HRECORD. + Callback function to receive the notifications... = no callback. + User instance data to pass to the callback function. + If successful, is returned, else is returned. Use to get the error code. + + When setting a notification callback on a channel, it only applies to the encoders that are currently set on the channel. Subsequent encoders will not automatically have the notification callback set on them, this function will have to be called again to set them up. + An encoder can only have one notification callback set. Subsequent calls of this function can be used to change the callback function, or disable notifications (proc = ). + The status of an encoder and its cast connection (if it has one) is checked when data is sent to the encoder or server, and by . That means an encoder's death will not be detected automatically, and so no notification given, while no data is being encoded. + If the encoder is already dead when setting up a notification callback, the callback will be triggered immediately. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + Using the callback with a recording caster: + + private ENCODENOTIFYPROC _myEndoderNotify; + private int _encoder = 0; + private int _recChan = 0; + private bool _autoreconnect = true; + ... + _recChan = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_DEFAULT, 20, null, IntPtr.Zero); + Start(); + ... + private void Start() + { + // start an encoder + _encoder = BassEnc.BASS_Encode_Start(_recChan, "lame -r -x -s 44100 -b 128 -", + BASSEncode.BASS_ENCODE_NOHEAD, null, IntPtr.Zero); + _myEndoderNotify = new ENCODENOTIFYPROC(EncoderNotify); + // start a caster + BassEnc.BASS_Encode_CastInit(_encoder, "server.com:8000", "password", + BassEnc.BASS_ENCODE_TYPE_MP3, "name", "url", "genre", null, null, 128, true); + // notify on dead encoder/connection + BassEnc.BASS_Encode_SetNotify(_encoder, _myEndoderNotify, IntPtr.Zero); + } + + private void Stop() + { + if (_encoder != 0) + { + BassEnc.BASS_Encode_SetNotify(_encoder, null, IntPtr.Zero); + BassEnc.BASS_Encode_Stop(_encoder); + _encoder = 0; + } + } + + private void EncoderNotify(int handle, int status, IntPtr user) + { + // encoder/connection lost + Stop(); + if (_autoreconnect) + { + // do auto-reconnect... + Thread.Sleep(1000); // wait a sec + Start(); + } + } + + + Private _myEndoderNotify As ENCODENOTIFYPROC + Private _encoder As Integer = 0 + Private _recChan As Integer = 0 + Private _autoreconnect As Boolean = True + ... + _recChan = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_DEFAULT, 20, Nothing, IntPtr.Zero) + Start() + ... + Private Sub Start() + ' start an encoder + _encoder = BassEnc.BASS_Encode_Start(_recChan, "lame -r -x -s 44100 -b 128 -", + BASSEncode.BASS_ENCODE_NOHEAD, Nothing, IntPtr.Zero) + _myEndoderNotify = New ENCODENOTIFYPROC(AddressOf EncoderNotify) + ' start a caster + BassEnc.BASS_Encode_CastInit(_encoder, "server.com:8000", "password", + Bass.BASS_ENCODE_TYPE_MP3, "name", "url", "genre", Nothing, Nothing, 128, True) + ' notify on dead encoder/connection + BassEnc.BASS_Encode_SetNotify(_encoder, _myEndoderNotify, IntPtr.Zero) + End Sub + + Private Sub Stop() + If _encoder <> 0 Then + BassEnc.BASS_Encode_SetNotify(_encoder, Nothing, IntPtr.Zero) + BassEnc.BASS_Encode_Stop(_encoder) + _encoder = 0 + End If + End Sub + + Private Sub EncoderNotify(handle As Integer, status As Integer, user As IntPtr) + ' encoder/connection lost + Stop() + If _autoreconnect Then + ' do auto-reconnect... + Thread.Sleep(1000) ' wait a sec + Start() + End If + End Sub + + + + + + Moves an encoder (or all encoders on a channel) to another channel. + + The encoder or channel handle... a HENCODE, HSTREAM, HMUSIC, or HRECORD. + The channel to move the encoder(s) to... a HSTREAM, HMUSIC, or HRECORD. + If successful, is returned, else is returned. Use to get the error code. + The new channel must have the same sample format (rate, channels, resolution) as the old channel, as that is what the encoder is expecting. + A channel's sample format is available via . + + + ERROR CODEDescription + BASS_ERROR_HANDLE or is not valid. + BASS_ERROR_FORMATThe new channel's sample format is not the same as the old channel's. + + + + + + + Retrieves the channel that an encoder is set on. + + The encoder to get the channel from. + If successful, the encoder's channel handle is returned, else 0 is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + + Initializes sending an encoder's output to a Shoutcast or Icecast server. + + The encoder handle. + The server to send to, in the form of "address:port" (Shoutcast v1) resp. "address:port,sid" (Shoutcast v2) or "address:port/mount" (Icecast). + The server password (a username can optionally also be included in the form "username:password", e.g. when connecting to a Shoutcast 2 server). + The MIME type of the encoder output. This can be one of the following: + , or . + + The stream name... = no name. + The URL, for example, of the radio station's webpage... = no URL. + The genre... = no genre. + Description... = no description. This applies to Icecast only. + Other headers to send to the server... = none. Each header should end with a carriage return and line feed ("\r\n"). + The bitrate (in kbps) of the encoder output... 0 = undefined bitrate. In cases where the bitrate is a "quality" (rather than CBR) setting, the headers parameter can be used to communicate that instead, eg. "ice-bitrate: Quality 0\r\n". + Public? If , the stream is added to the public directory of streams, at shoutcast.com or dir.xiph.org (or as defined in the server config). + If successful, is returned, else is returned. Use to get the error code. + + This function sets up a Shoutcast/Icecast source client, sending the encoder's output to a server, which listeners can then connect to and receive the data from. + The Shoutcast and Icecast server software is available from www.shoutcast.com/broadcast-tools and www.icecast.org/download, respectively. + An encoder needs to be started (but with no data sent to it yet) before using this function to setup the sending of the encoder's output to a Shoutcast or Icecast server. + If is used, the encoder should be setup to write its output to STDOUT. Due to the length restrictions of WAVE headers/files, the encoder should also be started with the BASS_ENCODE_NOHEAD flag, and the sample format details sent via the command-line. + Unless the BASS_ENCODE_CAST_NOLIMIT flag is set on the encoder, BASSenc automatically limits the rate that data is processed to real-time speed to avoid overflowing the server's buffer, which means that it is safe to simply try to process data as quickly as possible, eg. when the source is a decoding channel. + Encoders set on recording channels are automatically exempt from the rate limiting, as they are inherently real-time. + With BASS 2.4.6 or above, also exempt are encoders that are fed in a playback buffer update cycle (including and calls), eg. when the source is a playing channel; that is to avoid delaying the update thread, which could result in playback buffer underruns. + Normally, BASSenc will produce the encoded data (with the help of an encoder) that is sent to a Shoutcast/Icecast server, but it is also possible to send already encoded data to a server (without first decoding and re-encoding it) via the PCM encoding option. + The encoder can be set on any BASS channel, as rather than feeding on sample data from the channel, would be used to feed in the already encoded data. + BASSenc does not know what the data's bitrate is in that case, so it is up to the user to process the data at the correct rate (real-time speed). + can be used to setup a server that listeners can connect to directly, without a Shoutcast/Icecast server intermediary. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ALREADYThere is already a cast set on the encoder. + BASS_ERROR_ILLPARAM doesn't include a port number. + BASS_ERROR_FILEOPENCouldn't connect to the server. + BASS_ERROR_CAST_DENIED is not valid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Start encoding a stereo 44100hz channel to 128kb/s MP3, and send the output to a Shoutcast server: + + // setup the encoder + int encoder = BassEnc.BASS_Encode_Start(channel, "lame -r -x -s 44100 -b 128 -", + BASS_ENCODE_NOHEAD, null, 0); + // setup the encoder + BassEnc.BASS_Encode_CastInit(encoder, "server.com:8000", "password", BassEnc.BASS_ENCODE_TYPE_MP3, + "name", "url", "genre", null, null, 128, true); + + + ' setup the encoder + Dim encoder As Integer = BassEnc.BASS_Encode_Start(channel, "lame -r -x -s 44100 -b 128 -", + BASS_ENCODE_NOHEAD, Nothing, 0) + ' setup the encoder + BassEnc.BASS_Encode_CastInit(encoder, "server.com:8000", "password", BassEnc.BASS_ENCODE_TYPE_MP3, + "name", "url", "genre", Nothing, Nothing, 128, True) + + + + + + Sets the title of a cast stream (ANSI only). + + The encoder handle. + The title to set. + URL to go with the title... = no URL. This applies to Shoutcast only. + If successful, is returned, else is returned. Use to get the error code. + + This overload always uses an ANSI character string to update the title/url. + The ISO-8859-1 (Latin-1) character set should be used with Shoutcast servers, and UTF-8 with Icecast and Shoutcast 2 servers + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThere isn't a cast set on the encoder. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Sets the title of a cast stream. + + The encoder handle. + The encoded byte array containing the title to set. + The encoded byte array containing the URL to go with the title... = no URL. This applies to Shoutcast only. + If successful, is returned, else is returned. Use to get the error code. + + This overload allows you to pass an encoded byte array to update the title/url (e.g. when the server expects a specific codepage/character set). + The ISO-8859-1 (Latin-1) character set should be used with Shoutcast servers, and UTF-8 with Icecast and Shoutcast 2 servers + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThere isn't a cast set on the encoder. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + Sets a song title using UTF-8: + + Encoding utf8 = Encoding.UTF8; + BassEnc.BASS_Encode_CastSetTitle(encoder, utf8.GetBytes(song+"\0"), null); + + + Dim utf8 As Encoding = Encoding.UTF8 + BassEnc.BASS_Encode_CastSetTitle(encoder, utf8.GetBytes(song+"\0"), Nothing) + + + + + + Sends metadata to a Shoutcast 2 server. + + The encoder handle. + The type of metadata (one of the values). + This is a Shoutcast 2 message class (in bits 12 to 15) and type (bits 0 to 11) that describes what the metadata is. For example, 0x4001 is class 4 and type 1 (which would indicate a station logo in PNG format). + The metadata as an UTF-8 encoded byte array. + If successful, is returned, else is returned. Use to get the error code. + This method allows you to send an encoded UTF-8 byte array containing XML metadata to the server (SHOUTcast v2). + Some information on the available metadata options can be found in the Shoutcast 2 specs: wiki.winamp.com/wiki/SHOUTcast_2_(Ultravox_2.1)_Protocol_Details. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThere isn't a cast set on the encoder. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Sends metadata to a Shoutcast 2 server. + + The encoder handle. + The type of metadata (one of the values). + This is a Shoutcast 2 message class (in bits 12 to 15) and type (bits 0 to 11) that describes what the metadata is. For example, 0x4001 is class 4 and type 1 (which would indicate a station logo in PNG format). + The XML metadata to send. + If successful, is returned, else is returned. Use to get the error code. + This method allows you to send an encoded UTF-8 byte array containing XML metadata to the server (SHOUTcast v2). + Some information on the available metadata options can be found in the Shoutcast 2 specs: wiki.winamp.com/wiki/SHOUTcast_2_(Ultravox_2.1)_Protocol_Details. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThere isn't a cast set on the encoder. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + + + + + + + + + + Retrieves stats from the Shoutcast or Icecast server. + + The encoder handle. + The type of stats to retrieve. One of the following (see ): + + BASS_ENCODE_STATS_SHOUTShoutcast stats, including listener information and additional server information. + BASS_ENCODE_STATS_ICEIcecast mount-point listener information. + BASS_ENCODE_STATS_ICESERVIcecast server stats, including information on all mount points on the server. + + + Password when retrieving Icecast server stats... = use the password provided in the call. + If successful, is returned, else is returned. Use to get the error code. + The stats are returned in XML format. + Each encoder has a single stats buffer, which is reused by each call of this function for the encoder. + So if the data needs to be retained across multiple calls, it should be copied to another buffer. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThere isn't a cast set on the encoder. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + Get the number of listeners for SHOUTcast: + + string stats = BassEnc.BASS_Encode_CastGetStats(encoder, + BASSEncodeStats.BASS_ENCODE_STATS_SHOUT, password); + if (stats != null) + { + int start = stats.IndexOf( "<CURRENTLISTENERS>" ); + int end = stats.IndexOf( "</CURRENTLISTENERS>" ); + if (start > 0 && end > 0) + { + start += 18; + count = int.Parse( stats.Substring(start, end-start) ); + } + } + + + Dim stats As String = BassEnc.BASS_Encode_CastGetStats(encoder, + BASSEncodeStats.BASS_ENCODE_STATS_SHOUT, password) + If Not (stats Is Nothing) Then + Dim start As Integer = stats.IndexOf("<CURRENTLISTENERS>") + Dim [end] As Integer = stats.IndexOf("</CURRENTLISTENERS>") + If start > 0 AndAlso end > 0 Then + start += 18 + count = Integer.Parse(stats.Substring(start, end - start)) + End If + End If + + + + + + Initializes a server to send an encoder's output to connecting clients. + + The encoder handle. + The IP address and port number to accept client connections on... "xxx.xxx.xxx.xxx:port", = an available port on all local addresses. + The IP address should be local and the port number should be lower than 65536. If the address is "0.0.0.0" or omitted, then the server will accept connections on all local addresses. + If the port is "0" or omitted, then an available port will be assigned. + The server's buffer length in bytes. + The amount of buffered data to send to new clients. This will be capped at the size of the buffer. + A combination of these flags: + + BASS_ENCODE_SERVER_NOHTTPDo not read or send HTTP headers. + + + Callback function to receive notification of clients connecting and disconnecting... = no callback. + User instance data to pass to the callback function. + If successful, the new server's port number is returned, else 0 is returned. Use to get the error code. + + This function allows remote (or local) clients to receive the encoder's output by setting up a TCP server for them to connect to, using for example. + Connections can be refused by the callback function, and already connected clients can be kicked with the function. + The server buffers the data that it receives from the encoder, and the data is then sent from the buffer to the connected clients. The buffer should be at least big enough to account for the time that it takes for the clients to receive the data. If a client falls too far behind (beyond the buffer length), it will miss some data. When a client connects, buffered data can be "burst" to the client, allowing it to prebuffer and begin playback more quickly. + An encoder needs to be started, but with no data yet sent to it, before using this function to setup the server. If is used, the encoder should be setup to write its output to STDOUT. Due to the length restrictions of WAVE headers/files, the encoder should also be started with the BASS_ENCODE_NOHEAD flag, and the sample format details sent via the command-line. + Normally, BASSenc will produce the encoded data (with the help of an encoder) that is sent to a clients, but it is also possible to send already encoded data (without first decoding and re-encoding it) via the PCM encoding option. + The encoder can be set on any BASS channel, as rather than feeding on sample data from the channel, would be used to feed in the already encoded data. BASSenc does not know what the data's bitrate is in that case, so it is up to the user to process the data at the correct rate (real-time speed). + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ALREADYThere is already a server set on the encoder. + BASS_ERROR_ILLPARAM is not valid. + BASS_ERROR_BUSYThe port is in use. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + This function is not available on Windows CE. + + + Start encoding a stereo 44100Hz channel to 128kb/s MP3, and start a server on port 8000 with a fully burstable 4 second (64KB) buffer: + + // setup the encoder + int encoder = BassEnc.BASS_Encode_Start(channel, "lame -r -s 44100 -b 128 -", + BASSEncode.BASS_ENCODE_NOHEAD, null, IntPtr.Zero); + // start the server + BassEnc.BASS_Encode_ServerInit(encoder, "8000", 64000, 64000, + BASSEncodeServer.BASS_ENCODE_SERVER_DEFAULT, null, IntPtr.Zero); + + Start encoding a stereo 44100Hz channel to 160kb/s OGG, and start a server on any available port on the loopback address (127.0.0.1) with a fully burstable 2 second (40KB) buffer: + + // setup the encoder + int encoder = BassEnc.BASS_Encode_Start(channel, "oggenc -r -R 44100 -M 160 -m 160 -", + BASSEncode.BASS_ENCODE_NOHEAD, null, IntPtr.Zero); + // start the server + BassEnc.BASS_Encode_ServerInit(encoder, "127.0.0.1", 40000, 40000, + BASSEncodeServer.BASS_ENCODE_SERVER_DEFAULT, null, IntPtr.Zero); + + Setup PCM encoding on a dummy stream to feed pre-encoded data to a server on port 8000 with a 64KB buffer: + + // create a dummy stream to host the encoder + int dummy = Bass.BASS_StreamCreateDummy(44100, 1, BASSFlag.BASS_STREAM_DECODE, IntPtr.Zero); + // setup the encoder + int encoder = BassEnc.BASS_Encode_Start(dummy, null, + BASSEncode.BASS_ENCODE_PCM | BASSEncode.BASS_ENCODE_NOHEAD, + null, IntPtr.Zero); + // start the server + int port = BassEnc.BASS_Encode_ServerInit(encoder, "8000", 64000, 64000, + BASSEncodeServer.BASS_ENCODE_SERVER_DEFAULT, null, IntPtr.Zero); + ... + // feed encoded data to the encoder/server (repeat periodically) + BassEnc.BASS_Encode_Write(encoder, data, length); + + + + + + Kicks clients from a server. + + The encoder handle. + The client(s) to kick... "" (empty string) = all clients. Unless a port number is included, this string is compared with the start of the connected clients' IP address. + If successful, is returned, else is returned. Use to get the error code. + + The clients may not be kicked immediately, but shortly after the call. If the server has been setup with an callback function, that will receive notification of the disconnections. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILNo matching clients were found. + + + Platform-specific + This function is not available on Windows CE. + + + + + content MIME type for MP3 + + + + + content MIME type for OGG + + + + + content MIME type for AAC + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + Load BASS and BASSenc from the application's startup path: + + Bass.LoadMe(); + BassEnc.LoadMe(); + ... + // when not used anymore... + BassEnc.FreeMe(); + Bass.FreeMe(); + + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + Load BASS and BASSenc from a different directory: + + Bass.LoadMe( @"C:\Development\BASS\_libs" ); + BassEnc.LoadMe( @"C:\Development\BASS\_libs" ); + ... + // when not used anymore... + BassEnc.FreeMe(); + Bass.FreeMe(); + + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + BASS Encode Start flags for use with . + + + + + Default option, incl. wave header, little-endian and no FP conversion. + + + + + Do NOT send a WAV header to the encoder. + + + + + Convert floating-point sample data to 8-bit integer. + + + + + Convert floating-point sample data to 16-bit integer. + + + + + Convert floating-point sample data to 24-bit integer. + + + + + Convert floating-point sample data to 32-bit integer. + + + + + Big-Endian sample data. + + + + + Start the encoder paused. + + + + + Write PCM sample data (no encoder). + + + + + Write RF64 WAV header (no encoder). + + + + + Convert to mono (if not already). + + + + + Queue data to feed encoder asynchronously. + The queue buffer will grow as needed to fit the data, but its size can be limited by the config option (0 = no limit); the default is 10000ms. + If the queue reaches the size limit and data is lost, the notification will be triggered. + + + + + Don't limit the data rate (to real-time speed) when sending to a Shoutcast or Icecast server. + With this option you might disable the rate limiting during casting (as it'll be limited by the playback rate anyway if the source channel is being played). + + + + + Limit data rate to real-time. + Limit the data rate to real-time speed, by introducing a delay when the rate is too high. With BASS 2.4.6 or above, this flag is ignored when the encoder is fed in a playback buffer update cycle (including and calls), to avoid possibly causing playback buffer underruns. + Except for in those instances, this flag is applied automatically when the encoder is feeding a Shoutcast or Icecast server. + + + + + Free the encoder when the channel is freed. + + + + + Cmdline is Unicode (16-bit characters). + + + + + ACM Format flags to be used with . + + + + + No ACM. + + + + + Use the format as default selection. + + + + + Only list formats with same sample rate as the source channel. + + + + + Only list formats with same number of channels (eg. mono/stereo). + + + + + Suggest a format (HIWORD=format tag - use one of the flags). + + + + + Unicode (16-bit characters) option. + + + + + To be used with to receive notifications on an encoder's status. + + + + + Encoder died. + + + + + Cast server connection died. + + + + + Cast timeout. + + + + + Async encoding queue is out of space. + + + + + Encoder has been freed. + + + + + To be used with to define the type of count you want to get. + + + + + Get the bytes sent to the encoder. + + + + + Get the bytes received from the encoder. + + + + + Get the bytes sent to the cast server. + + + + + Data currently in the queue, waiting to be sent to the encoder (if async encoding is enabled). + + + + + The queue's size limit (if async encoding is enabled). + + + + + Data not queued due to the queue being full or out of memory (if async encoding is enabled). + + + + + To be used with to define the type of metadata to send. + + + + + SHOUTcast v2 Cacheable Metadata (Content Info Metadata). + + + + + SHOUTcast v2 Cacheable Metadata (Url Metadata). + + + + + SHOUTcast v2 Cacheable Metadata (Aol Radio format). + + + + + SHOUTcast v2 Cacheable Metadata (SHOUTcast 2.0 format). + + + + + SHOUTcast v2 Cacheable Binary Metadata (Station logo image/jpeg). + + + + + SHOUTcast v2 Cacheable Binary Metadata (Station logo image/png). + + + + + SHOUTcast v2 Cacheable Binary Metadata (Station logo image/bmp). + + + + + SHOUTcast v2 Cacheable Binary Metadata (Station logo image/gif). + + + + + SHOUTcast v2 Cacheable Binary Metadata (Album art image/jpeg). + + + + + SHOUTcast v2 Cacheable Binary Metadata (Album art image/png). + + + + + SHOUTcast v2 Cacheable Binary Metadata (Album art image/bmp). + + + + + SHOUTcast v2 Cacheable Binary Metadata (Album art image/gif). + + + + + SHOUTcast v2 Pass-through Metadata (Time Remaining). + + + + + To be used with to define the type of stats you want to get. + + + + + Shoutcast stats. + + + + + Icecast mount-point stats. + + + + + Icecast server stats. + + + + + To be used with to define optional server flags. + + + + + Default (no options). + + + + + No HTTP headers. + + + + + The ACMFORMAT is a specialized and generic format structure. It contains the WAVEFORMATEX structure and define the format of any ACM audio data. + Only format information common to all ACM audio data formats are included in this structure. + For formats that require additional information, this structure has an additional byte[] keeping the additional information. + + + + + The structure that specifies the basic format. + + + + + Extra format information is appended to the end of the WAVEFORMATEX structure in this array. + This information can be used by non-PCM formats to store extra attributes for the wFormatTag. + If no extra information is required by the wFormatTag, this member should be set to zero. + For WAVE_FORMAT_PCM formats (and only WAVE_FORMAT_PCM formats), this member is ignored. + + + + + Creates an instance of a generic audio codec format and automatically determines the suggested format buffer length. + + + + + Creates an instance of a generic audio codec format with a given total length. + + The total lenght of the format structure (e.g. as returned by when using 0 for the formlen parameter). + + + + + + Creates an instance of a generic audio codec format from the given format buffer pointer. + + A pointer to an ACM codec format structure as returned by . + + + ACMFORMAT codec = null; + // get the maximum codec format length + int formlen = BASS_Encode_GetACMFormat(0, IntPtr.Zero, 0, null, BASSACMFormat.BASS_ACM_NONE); + byte[] buffer = new byte[formlen]; + GCHandle hGC = GCHandle.Alloc( buffer, GCHandleType.Pinned ); + try + { + IntPtr codecPtr = hGC.AddrOfPinnedObject(); + if ( BassEnc.BASS_Encode_GetACMFormat( handle, codecPtr, formlen, title, flags) > 0 ) + { + codec = new ACMFORMAT(codecPtr); + } + } + catch { codec = null; } + finally + { + hGC.Free(); + } + + + Dim codec As ACMFORMAT = Nothing + ' get the maximum codec format length + Dim formlen As Integer = BASS_Encode_GetACMFormat(0, IntPtr.Zero, 0, Nothing, BASSACMFormat.BASS_ACM_NONE) + Dim buffer(formlen - 1) As Byte + Dim hGC As GCHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned) + Try + Dim codecPtr As IntPtr = hGC.AddrOfPinnedObject() + If BassEnc.BASS_Encode_GetACMFormat(handle, codecPtr, formlen, title, flags) > 0 Then + codec = New ACMFORMAT(codecPtr) + End If + Catch + codec = Nothing + Finally + hGC.Free() + End Try + + If you are into C# you might also use native pointers in an unsafe codeblock: + + ACMFORMAT codec = null; + // get the maximum codec format length + int formlen = BASS_Encode_GetACMFormat(0, IntPtr.Zero, 0, null, BASSACMFormat.BASS_ACM_NONE); + byte[] buffer = new byte[formlen]; + unsafe + { + fixed (byte* p = buffer) + { + if ( BassEnc.BASS_Encode_GetACMFormat( handle, (IntPtr)p, formlen, title, flags) > 0 ) + { + codec = new ACMFORMAT((IntPtr)p); + } + } + } + + + + + + Returns a description string for the instance members. + + Returns a description string for the instance members (wFormatTag, res, nSamplesPerSec, chans). + + + + Saves codec format data to a file name. + + The as returned by . + The file name to save the ACM codec format data to. + on success, else . + Use to (re)create an instance of an codec format. + This method might be usefull together with , or + in order to load and save predefined codec'. + + + + + Loads codec format data from a file. + + The file name from where to load the ACM codec format data. + On success an instance of is returned, else is returned. + Use to write the instance data of an codec format to a file. + This method might be usefull together with , or + in order to load and save predefined codec's. + + + + + Returns the total length of this instance. + + + + + User defined callback function to process (receive) encoded sample data. + + The encoder that the data is from (as returned by ). + The channel that the data is from. + The pointer to the buffer containing the encoded data. + The number of bytes in the buffer. + The user instance data given when was called. + + To have the encoded data received by this callback function, the encoder needs to be told to output to STDOUT (instead of a file). + + It is clever to NOT alloc any buffer data (e.g. a byte[]) everytime within the callback method, since ALL callbacks should be really fast! + And if you would do a 'byte[] data = new byte[]' every time here...the GarbageCollector would never really clean up that memory. + Sideeffects might occure, due to the fact, that BASS will call this callback too fast and too often... + + NOTE: When you pass an instance of a callback delegate to one of the BASS functions, this delegate object will not be reference counted. + This means .NET would not know, that it might still being used by BASS. The Garbage Collector might (re)move the delegate instance, if the variable holding the delegate is not declared as global. + So make sure to always keep your delegate instance in a variable which lives as long as BASS needs it, e.g. use a global variable or member. + + + + // the encoding callback + private ENCODEPROC _myEndoderProc; + private byte[] _encbuffer = new byte[1048510]; // 1MB buffer + ... + _myEndoderProc = new ENCODEPROC(MyEncodingWriter); + // create the encoder (with default setting for lame) + BassEnc.BASS_Encode_Start(channel, "lame --alt-preset standard", + BASSEncode.BASS_ENCODE_DEFAULT, _myEndoderProc, IntPtr.Zero); + Bass.BASS_ChannelPlay(channel, false); // start the channel playing & encoding + ... + private bool MyEncodingWriter(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + // copy from managed to unmanaged memory + Marshal.Copy(buffer, _encbuffer, 0, length); + // process the data in _encbuffer, e.g. write to disk or whatever + ... + } + + + Private _myEndoderProc As ENCODEPROC + Private _encbuffer(1048510) As Byte ' 1MB buffer + ... + _myEndoderProc = New ENCODEPROC(AddressOf MyEncodingWriter) + ' create the encoder (with default setting for lame) + BassEnc.BASS_Encode_Start(channel, "lame --alt-preset standard", + BASSEncode.BASS_ENCODE_DEFAULT, _myEndoderProc, IntPtr.Zero) + Bass.BASS_ChannelPlay(channel, False) + ' start the channel playing & encoding + Private Function MyEncodingWriter(handle As Integer, channel As Integer, + buffer As IntPtr, length As Integer, user As IntPtr) As Boolean + ' copy from managed to unmanaged memory + Marshal.Copy(buffer, _encbuffer, 0, length) + ' process the data in _encbuffer, e.g. write to disk or whatever + ... + End Function + + If you are into C# you might also use native pointer access in an unsafe code block: + + // assuming you have created a: BinaryWriter bw = new BinaryWriter(_fs); + private unsafe bool MyEncodingWriter(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + byte *data = (byte*)buffer; + // process the data in 'data', e.g. write to disk or whatever + for (int a=0; a<length; a++) + { + // write the received sample data to a local file + bw.Write( data[a] ); + } + } + + + + + + User defined callback function to receive notifications on an encoder's status. + + The encoder that the notification is from (as returned by ). + The encoder's status, one of the following (see ): + BASS_ENCODE_NOTIFY_ENCODER : The encoder died. + BASS_ENCODE_NOTIFY_CAST : Cast server connection died. + BASS_ENCODE_NOTIFY_CAST_TIMEOUT : Cast data sending timeout. The connection is not dead at this point, it may just be a temporary problem. + BASS_ENCODE_NOTIFY_QUEUE_FULL : The queue length has reached its limit (or out of memory) and data has been dropped. The total amount of dropped data is available from . + BASS_ENCODE_NOTIFY_FREE : The encoder has been freed. + + The user instance data given when was called. + + When setting a notification callback on a channel, it only applies to the encoders that are currently set on the channel. Subsequent encoders will not automatically have the notification callback set on them, this function will have to be called again to set them up. + An encoder can only have one notification callback set. Subsequent calls of this function can be used to change the callback function, or disable notifications (proc = ). + If the encoder is already dead when setting up a notification callback, the callback will be triggered immediately. + It is safe to call to free an encoder from within a notification callback. + + + Using the callback with a recording caster: + + private ENCODENOTIFYPROC _myEndoderNotify; + private int _encoder = 0; + private int _recChan = 0; + private bool _autoreconnect = true; + ... + _recChan = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_DEFAULT, 20, null, IntPtr.Zero); + Start(); + ... + private void Start() + { + // start an encoder + _encoder = BassEnc.BASS_Encode_Start(_recChan, "lame -r -x -s 44100 -b 128 -", + BASSEncode.BASS_ENCODE_NOHEAD, null, IntPtr.Zero); + _myEndoderNotify = new ENCODENOTIFYPROC(EncoderNotify); + // start a caster + BassEnc.BASS_Encode_CastInit(_encoder, "server.com:8000", "password", + BassEnc.BASS_ENCODE_TYPE_MP3, "name", "url", "genre", null, null, 128, true); + // notify on dead encoder/connection + BassEnc.BASS_Encode_SetNotify(_encoder, _myEndoderNotify, IntPtr.Zero); + } + + private void Stop() + { + if (_encoder != 0) + { + BassEnc.BASS_Encode_SetNotify(_encoder, null, IntPtr.Zero); + BassEnc.BASS_Encode_Stop(_encoder); + _encoder = 0; + } + } + + private void EncoderNotify(int handle, BASSEncodeNotify status, IntPtr user) + { + // encoder/connection lost + Stop(); + if (_autoreconnect) + { + // do auto-reconnect... + Thread.Sleep(1000); // wait a sec + Start(); + } + } + + + Private _myEndoderNotify As ENCODENOTIFYPROC + Private _encoder As Integer = 0 + Private _recChan As Integer = 0 + Private _autoreconnect As Boolean = True + ... + _recChan = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_DEFAULT, 20, Nothing, IntPtr.Zero) + Start() + ... + Private Sub Start() + ' start an encoder + _encoder = BassEnc.BASS_Encode_Start(_recChan, "lame -r -x -s 44100 -b 128 -", + BASSEncode.BASS_ENCODE_NOHEAD, Nothing, IntPtr.Zero) + _myEndoderNotify = New ENCODENOTIFYPROC(AddressOf EncoderNotify) + ' start a caster + BassEnc.BASS_Encode_CastInit(_encoder, "server.com:8000", "password", + Bass.BASS_ENCODE_TYPE_MP3, "name", "url", "genre", Nothing, Nothing, 128, True) + ' notify on dead encoder/connection + BassEnc.BASS_Encode_SetNotify(_encoder, _myEndoderNotify, IntPtr.Zero) + End Sub + + Private Sub Stop() + If _encoder <> 0 Then + BassEnc.BASS_Encode_SetNotify(_encoder, Nothing, IntPtr.Zero) + BassEnc.BASS_Encode_Stop(_encoder) + _encoder = 0 + End If + End Sub + + Private Sub EncoderNotify(handle As Integer, status As BASSEncodeNotify, user As IntPtr) + ' encoder/connection lost + Stop() + If _autoreconnect Then + ' do auto-reconnect... + Thread.Sleep(1000) ' wait a sec + Start() + End If + End Sub + + + + + + User defined callback function to receive notification of client connections and disconnections, and optionally refuse connections. + + The encoder/server that the client is connecting to or disconnecting from (as returned by ). + The client is connecting? TRUE = connecting, FALSE = disconnecting. + The client's IP address and port number... "xxx.xxx.xxx.xxx:port". + The request headers... = the client is disconnecting or HTTP headers have been disabled via the BASS_ENCODE_SERVER_NOHTTP flag. + The headers are in the same form as would be given by , which is a series of null-terminated strings, the final string ending with a double null. + The request headers can optionally be replaced with response headers to send back to the client, each ending with a carriage return and line feed ("\r\n"). + The response headers should not exceed 1KB in length. + The user instance data given when was called. + If the client is connecting, means the connection is denied, otherwise it is accepted. The return value is ignored if the client is disconnecting. + + This function can be used to keep track of how many clients are connected, and who is connected. + The request headers can be used to authenticate clients, and response headers can be used to pass information back to the clients. + By default, connecting clients will be sent an "HTTP/1.0 200 OK" status line if accepted, and an "HTTP/1.0 403 Forbidden" status line if denied. + That can be overridden in the first response header. + Disconnection notifications will be received for clients that have disconnected themselves or that have been kicked by , but there will no notification of any clients that are disconnected by the encoder being freed. + Each server has its own thread that handles new connections and sends data to its clients. The notification callbacks also come from that thread, so the callback function should avoid introducing long delays as that could result in clients missing some data and delay other clients connecting. + To access the 'headers' data use one of the following utility methods: + To read the headers use the helper method; + to write to the headers use the helper method. + + + + A callback function that only allows connections from the 196.168/16 network, and only 5 clients: + + int _listeners = 0; // client count + + private bool EncodeClientProc(int handle, bool connect, string client, IntPtr headers, IntPtr user) + { + if (connect) + { + if (_listeners == 5) + { + // hit client limit + string[] resHeaders = new string[1] { "HTTP/1.0 403 Server Full" }; + // set custom status + Utils.StringToNullTermAnsi(resHeaders, headers, true); + // refuse the connection + return false; + } + if (!client.StartsWith("192.168.")) + { + // not on the 196.168/16 network + // refuse the connection + return false; + } + // increment the client count + _listeners++; + } + else + { + // decrement the client count + _listeners--; + } + return true; + } + + A callback function that only allows connections with a particular "User-Agent" request header: + + private bool EncodeClientProc(int handle, bool connect, string client, IntPtr headers, IntPtr user) + { + if (connect) + { + // get the received headers + string[] getHeaders = Utils.IntPtrToArrayNullTermAnsi(headers); + // find the User-Agent header + foreach (string content in getHeaders) + { + if (content.StartsWith("User-Agent:")) + { + // found the User-Agent header + if (content.Substring(11) != "Special Agent") + return false; + break; + } + } + } + return true; + } + + + + + + BASS.NET API wrapper for BASSWV.DLL + Requires: basswv.dll - WavPack Audio Format (WV) Add-On - available @ www.un4seen.com. + + + BASSWV is an extension to the BASS audio library, enabling the playback of WavPack files. + WavPack is a completely open audio compression format providing lossless, high quality lossy, and an unique hybrid compression mode. + In the default lossless mode WavPack acts just like a WinZip® compressor for audio files. Unlike MP3 or WMA encoding which can affect the sound quality, + not a single bit of the original information is lost. The hybrid mode provides all the advantages of lossless compression with an additional bonus: instead of creating a single file, this mode creates both a + relatively small, high quality lossy file that can be used all by itself, and a correction file that, when combined with the lossy file, provides full lossless restoration. + The WavPack format is used in the same way as any of the built-in BASS stream formats. Simply call to load the add-on into BASS and benefit the usage of the standard sample/stream/user functions, or call the / User functions. + More information can be found on www.wavpack.com. + + + + + NOT used - all members are static! + + + + + + + + + + + + + + + + Creates a sample stream from a WavPack file. + This overload implements Unicode filenames. The BASS_UNICODE flag will be added automatically. + + Filename for which a stream should be created. + File offset to begin streaming from. + Data length... 0 = use all data up to the end of the file. + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + + + + + + + + + + + + Creates a sample stream from a WavPack memory IntPtr. + This overload implements streaming from memory. + + An unmanaged pointer to the memory location as an IntPtr. + Offset to begin streaming from (unused for memory streams, set to 0). + Data length (needs to be set to the length of the memory streams in bytes which should be played). + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + Creates a sample stream from a WavPack file via a user callback function. + + File system to use: see . + Any combination of these flags: see . + The user defined file functions (see ). + User instance data to pass to the callback functions. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + See . + + + + + + + + + + + + + + + Creates a sample stream from an WavPack file on the internet, optionally receiving the downloaded data in a callback. + + URL of the file to stream. Should begin with "http://" or "ftp://". + File position to start streaming from. This is ignored by some servers, specifically when the file length is unknown. + Any combination of these flags: see . + Callback function to receive the file as it is downloaded... = no callback. + User instance data to pass to the callback function. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + Supported file extensions of the basswv.dll + + + + + Supported file format name of the basswv.dll + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + The disadvantage of this method is, that the standard plugin support for is not working - so you would need to use the native add-on methods! + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + BASS.NET API wrapper for BASS_WADSP.DLL + Requires: bass_wadsp.dll - Winamp DSP plugin support Add-On - shipped with the BASS.NET API. + + + BassWaDsp is an BASS.NET API extention to the BASS audio library, providing a set of functions for calling Winamp DSP plugins. + All Winamp DSPs are supported out of the box which do return as much data as provided - meaning not modifying the samplerate, tempo, pitch etc.! + If you want to use Winamp plugins which do not return the same amount of bytes as provided, you need to add a lot functionality by yourself, e.g. implementing an intermediate ring-buffer between BASS and BASS_WADSP and/or sending ModifiedSamples only in a fixed packet size of 1152 samples etc. This might be a lot of work, but is actually possible. + However, there is no guarantee, that all Winmap DSPs might really work - just try them out. + Here is a list of Winamp DSP plugins, which should work fine: + + - OctiMax (dsp_omxw.dll) + - Enhancer (dsp_enh.dll) + - RockSteady (DSP_RockSteady.dll) + - Nullsoft Signal Processing Studio (dsp_sps.dll) + - SHOUTcast Source DSP (dsp_sc.dll - needs lamedll.dll in your startup directory) + - SAM Encoders (dsp_encoders.dll) + - Sound Solution (dsp_ss.dll - needs the ssN.dat files in your startup directory) + - VST PlugIn Wrapper (dsp_vst.dll) + - EQ by Nevi (dsp_eqfir.dll) + - DFX Audio Enhander (dsp_dfx.dll) + + + These plugins for example will only work, if you implement an intermediate ring-buffer between BASS and BASS_WADSP by yourself: + + - Reverb3 (dsp_reverb3.dll - working with fixed Packets of 1152 samples only) + - TomSteady (dsp_tom.dll - working with fixed Packets of 1152 samples only) + - PaceMaker (dsp_pacemaker.dll) + + + Any window that remains in foreground should optimally pass unusedkeystrokes to the parent (winamp's) window, so that the user can still control it. + As for storing configuration, configuration data should be stored in [startup path]\plugin.ini. + To use the BASS_WADSP add-on you need to perform the following steps: + + 1.Call at the beginning of your application after you have initialized Bass with . + 2.Call - to load a Winamp DSP plugin. + 3.Call - to start the loaded Winamp DSP plugin. + 4.Create a Bass stream...e.g. with . + 5.Call - to set the Winamp DSP to the created stream. This assigns a normal Bass DSP (like you would do with ) but now uses the Winamp DSP internally. + You might even assign multiple Winamp DSPs to the same stream. In this case the DSPs are just executed in the order to their priority - like in Bass. + 6.Play the channel like normal...and at the end call (if BASS_STREAM_AUTOFREE was specified at stream creation or if you call this will be done automatically and removing the DSP(s) is not even needed). + 7.You might repeat with 4. + 8.When a Winamp DSP is not needed anymore, call - to stop the Winamp DSP plugin and call to start it again. + If you don't want the DSP anymore at all, you might also need to call in addition, if you have assigned multiple DSPs to the stream in parallel. + 9.Call - to unload a Winamp DSP plugin and free all resources (this also stops the DSP and removes it out of memory). + 10.At the end of your application make sure to call - to free all resources. + + + + + + + Current BASS_WADSP version (without minor revision). + + + + + NOT used - all members are static! + + + + + Retrieves the version number of the BASS_WADSP.DLL that is loaded. + + The BASS_WADSP version. For example, 0x02040103 (hex), would be version 2.4.1.3. + There is no guarantee that a previous or future version of BASS_WADSP supports all the BASS_WADSP functions that you are using, so you should always use this function to make sure the correct version is loaded. + It is safe to assume that future minor revisions (indicated in the LOWORD) will be fully compatible. + You might use the global constant to check the major revision. + Note: Calling this method will also automatically load the library into memory. + + + Checking the major version only: + + if ( Utils.HighWord(BassWaDsp.BASS_WADSP_GetVersion()) != BassWaDsp.BASSWADSPVERSION ) + { + MessageBox.Show(this, "Wrong BassWaDsp Version!"); + } + + + If Utils.HighWord(BassWaDsp.BASS_WADSP_GetVersion()) <> BassWaDsp.BASSWADSPVERSION Then + MessageBox.Show(Me, "Wrong BassWaDsp Version!") + End If + + Checking for full version "2.4.1.3": + + if (BassWaDsp.BASS_WADSP_GetVersion() < Utils.MakeLong(0x0103, 0x0204)) + { + MessageBox.Show(this, "Wrong BassWaDsp Version!"); + } + + + If BassWaDsp.BASS_WADSP_GetVersion() < Utils.MakeLong(&H103, &H204) Then + MessageBox.Show(Me, "Wrong BassWaDsp Version!") + End If + + + + + + Retrieves the version of the BASS_WADSP.DLL that is loaded. + + The number of components to use. The fieldCount ranges from 1 to 4 (major.minor.build.revision). + The BASS_FX version (major.minor.build.revision). + There is no guarantee that a previous or future version of BASS_WADSP supports all the BASS_WADSP functions that you are using, so you should always use this function to make sure the correct version is loaded. + It is safe to assume that future minor revisions (indicated in the LOWORD) will be fully compatible. + Note: Calling this method will also automatically load the library into memory. + + + + Version expectedVersion = new Version(2, 4); + if (BassWaDsp.BASS_WADSP_GetVersion(2) < expectedVersion) + { + MessageBox.Show( this, "Wrong BassWaDsp Version!" ); + } + + + Dim expectedVersion As New Version(2, 4) + If BassWaDsp.BASS_WADSP_GetVersion(2) < expectedVersion Then + MessageBox.Show(Me, "Wrong BassWaDsp Version!") + End If + + + + + + Initializes BASS_WADSP, call this right after you have called . + + The main window handle of your application (e.g. this.Handle) - or for console applications. + on success, else . Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_ALREADY has already been called and can not be called again. + + + + + + + Frees all resources of BASS_WADSP - call this method at the end of your application. + + on success, else . Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_INIT has not been called before. + + + + + + + Frees and unloads a Winamp DSP library from memory which has been loaded with before. + + The plugin handle to unload (as returned by ). + on success, else . Use to get the error code. + The Winamp DSP will automatically be stopped, if it was started before. + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe is not a valid plugin handle. + + + + + + + Gets the window handle of the fake Winamp window which has been created internally when a Winamp DSP was loaded with . + + The plugin handle (returned by ). + An IntPtr representing the window handle of the fake Winamp window or if an error occured. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe is not a valid plugin handle. + BASS_ERROR_UNKNOWNSome other problem (the internal fake Winamp window could not be created). + + + + + + + Set the song title for a loaded Winamp DSP plugin. + + The plugin handle (returned by ). + The song title to set. + on success, else . Use to get the error code. + Some Winamp DSPs require or simply display a current song title. Use this method to set this song title. It will then be used in the internal Window message handler for the related fake Winamp window. + In most cases it is not required to set any song title at all - however streaming DSP might use this for updating it's metadata. + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe is not a valid plugin handle. + + + + + + + Set the file name for a loaded Winamp DSP plugin. + + The plugin handle (returned by ). + The file name to set. + on success, else . Use to get the error code. + Some Winamp DSPs require or simply display a current playing file name. Use this method to set this file name. It will then be used in the internal Window message handler for the related fake Winamp windows. + In most cases it is not required to set any file name at all. + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe is not a valid plugin handle. + + + + + + + Loads a Winamp DSP library. + + The fully qualified path and name of the Winamp DSP library you want to load (e.g. "C:\\Program Files\\Winamp\\Plugins\\dsp_ss.dll"). + Both Unicode as well as Ansi filenames are supported, whereas Unicode is tried first. + The X-coordinate of the fake Winamp window to create. + The Y-coordinate of the fake Winamp window to create. + The width of the fake Winamp window to create. + The height of the fake Winamp window to create. + An optional which should be used instead of the internal window process message handler. Or , if you want BASS_WADSP to handle it by default. + The handle of the loaded plugin, which is needed in all further method calls. + Most Winamp DSP plugins do save their location and visibility state in an own .ini file. So the parameters specifying the location and size are in most cases only uses for the first time a plugin is used. So don't worry, if they do not take effect. + In most cases the internal Windows message process handler should be fine and sufficient - however, if you encounter problems you might implement your own. + Make sure to call when the Winamp DSP is not needed anymore and should be unloaded and removed from memory. + Winamp DSPs are designed to run only for one stream. So if you have multiple streams or multiple players in your application and you want to use the same Winamp DSP you need to create temporary copies of the library files (e.g. copy "dsp_ss.dll" to "dsp_ss2.dll", "dsp_ss3.dll" etc.). + Then you should load each individual library copy with this function. This will enable you to load multiple instances of the same Winamp DSP. Each loaded instance can then be used for individual streams. + NOTE: Do not use this method while you have already loaded the same Winamp plugin, as this might result in any unexpected behavior, since some Winamp plugins might crash when they are loaded twice. + + + ERROR CODEDescription + BASS_ERROR_FILEOPENThe can not be found or loaded. + BASS_ERROR_FILEFORMThe doesn't seem to be a Winamp DSP library file. + BASS_ERROR_UNKNOWNSome other problem (the internal fake Winamp window could not be created). + + + + + + int dspPluginA = BassWaDsp.BASS_WADSP_Load("dsp_test.dll", 5, 5, 100, 100, null); + if (dspPluginA != 0) + { + BassWaDsp.BASS_WADSP_Start(dspPluginA, 0, 0); + } + + + Dim dspPluginA As Integer = BassWaDsp.BASS_WADSP_Load("dsp_test.dll", 5, 5, 100, 100, Nothing) + If dspPluginA <> 0 Then + BassWaDsp.BASS_WADSP_Start(dspPluginA, 0, 0) + End If + + + + + + Invokes the config dialog of a loaded and started Winamp DSP. + + The plugin handle (returned by ). + on success, else . Use to get the error code. + The Winamp DSP must have been started via prior to calling this method. + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe is not a valid plugin handle. + BASS_ERROR_START has not been called before. + + + + + + + Starts a Winamp DSP. + + The plugin handle (returned by ). + The module number to start (the first module is 0). + The BASS channel handle (HSTREAM, HMUSIC, or HRECORD) for which to start the Winamp DSP. Or 0 if not applicable. + on success, else . Use to get the error code. + Winamp DSPs might provide multiple independent modules. You might get the number of available modules with or the name of a certain module with . + However, you can only start one module at a time for a certain Winamp DSP. + The stream channel is only needed here because some Winamp DSPs might already request some information, which can be provided in this case. However, if you don't have created a stream so far, just leave the value to 0 and all is fine. + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe or the is not a valid handle. + BASS_ERROR_ILLPARAMThe is not a valid module. + BASS_ERROR_ALREADYThe plugin/module was already started (you need to call before starting it again). + BASS_ERROR_UNKNOWNSome other plugin problem (the plugin could not be initialized). + + + + + + + Stops a Winamp DSP. + + The plugin handle (returned by ). + on success, else . Use to get the error code. + If the Winamp DSP was already assigned to a channel using the DSP will be removed automatically from the channel when it is stopped. + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe is not a valid plugin handle. + BASS_ERROR_START has not been called before. + + + + + + + Assigns a channel to a Winamp DSP. + You only need this method, if you do NOT use the default method, but use your own DSP callback (see ). + + The plugin handle (returned by ). + The BASS channel handle (HSTREAM, HMUSIC, or HRECORD) which to assign to the Winamp DSP. + on success, else . Use to get the error code. + You must use this method when implementing your own callback before starting to play the channel. + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe or is not a valid handle. + + + + + + private int _streamA = 0; + private int _dspPluginA = 0; + private DSPPROC _myDSPAddr; + ... + _dspPluginA = BassWaDsp.BASS_WADSP_Load("dsp_test.dll", 5, 5, 100, 100, null); + BassWaDsp.BASS_WADSP_Start(_dspPluginA, 0, 0); + ... + _streamA = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, + BASSFlag.BASS_DEFAULT | BASSFlag.BASS_STREAM_AUTOFREE); + // play the stream + if (_streamA != 0 ) + { + _myDSPAddr = new DSPPROC(MyWinampDSP); + Bass.BASS_ChannelSetDSP(_streamA, _myDSPAddr, new IntPtr(_dspPluginA), -500); + BassWaDsp.BASS_WADSP_SetChannel(_dspPluginA, _streamA); + Bass.BASS_ChannelPlay(_streamA, false); + } + ... + private void MyWinampDSP(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + if (length == 0 || buffer == IntPtr.Zero) + return; + BassWaDsp.BASS_WADSP_ModifySamplesDSP(user.ToInt32(), buffer, length); + } + + + Private _streamA As Integer = 0 + Private _dspPluginA As Integer = 0 + Private _myDSPAddr As DSPPROC + ... + _dspPluginA = BassWaDsp.BASS_WADSP_Load("dsp_test.dll", 5, 5, 100, 100, Nothing) + BassWaDsp.BASS_WADSP_Start(_dspPluginA, 0, 0) + ... + _streamA = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, + BASSFlag.BASS_DEFAULT Or BASSFlag.BASS_STREAM_AUTOFREE) + ' play the stream + If _streamA <> 0 Then + _myDSPAddr = New DSPPROC(AddressOf MyWinampDSP) + Bass.BASS_ChannelSetDSP(_streamA, _myDSPAddr, New IntPtr(_dspPluginA), - 500) + BassWaDsp.BASS_WADSP_SetChannel(_dspPluginA, _streamA) + Bass.BASS_ChannelPlay(_streamA, False) + End If + ... + Private Sub MyWinampDSP(handle As Integer, channel As Integer, + buffer As IntPtr, length As Integer, user As IntPtr) + If length = 0 OrElse buffer = IntPtr.Zero Then + Return + End If + BassWaDsp.BASS_WADSP_ModifySamplesDSP(user.ToInt32(), buffer, length) + End Sub + + + + + + Returns the currently selected plugin module of a Winamp DSP. + + The plugin handle (returned by ). + The selected module number (first = 0), or -1, if an error occured. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe is not a valid plugin handle. + BASS_ERROR_START was not called (no module selected so far). + + + + + + + Assigns a loaded Winamp DSP to a standard BASS channel as a new DSP. + This method is pretty close to the method (which is in fact internally used) but instead of setting up a user DSP method the Winamp DSP will be set up. + + The plugin handle (returned by ). + The BASS channel handle (HSTREAM, HMUSIC, or HRECORD) which to assign to the Winamp DSP. + The priority of the new DSP, which determines it's position in the Bass DSP chain - DSPs with higher priority are called before those with lower. + If succesful, then the new DSP's handle (HDSP) is returned, else 0 is returned. Use to get the error code. + This method can and should only be used with those Winamp DSPs which return exactly as much samples as provided - meaning not modifying the samplerate, tempo, pitch etc.! + The Winamp DSP and this method can be used with 8-bit, 16-bit or float channels. Since all Winamp DSPs will internally only work with 16-bit channels an automatic internal conversion from 8-bit resp. float to 16-bit and back will take place. + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe or is not a valid handle. + + + + + + private int _streamA = 0; + private int _dspPluginA = 0; + ... + _dspPluginA = BassWaDsp.BASS_WADSP_Load("dsp_test.dll", 5, 5, 100, 100, null); + BassWaDsp.BASS_WADSP_Start(_dspPluginA, 0, 0); + ... + // create the stream + _streamA = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, + BASSFlag.BASS_DEFAULT | BASSFlag.BASS_STREAM_AUTOFREE); + // play the stream + if (_streamA != 0 ) + { + // the next will setup a DSP on the playing channel to the selected Winamp DSP + int hDsp = BassWaDsp.BASS_WADSP_ChannelSetDSP(this._dspPluginA, _streamA, 1); + // and finally play it + Bass.BASS_ChannelPlay(_streamA, false); + } + + + Private _streamA As Integer = 0 + Private _dspPluginA As Integer = 0 + ... + _dspPluginA = BassWaDsp.BASS_WADSP_Load("dsp_test.dll", 5, 5, 100, 100, Nothing) + BassWaDsp.BASS_WADSP_Start(_dspPluginA, 0, 0) + ... + ' create the stream + _streamA = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, + BASSFlag.BASS_DEFAULT Or BASSFlag.BASS_STREAM_AUTOFREE) + ' play the stream + If _streamA <> 0 Then + ' the next will setup a DSP on the playing channel to the selected Winamp DSP + Dim hDsp As Integer = BassWaDsp.BASS_WADSP_ChannelSetDSP(Me._dspPluginA, _streamA, 1) + ' and finally play it + Bass.BASS_ChannelPlay(_streamA, False) + End If + + + + + + Removes a Winamp DSP from the Bass DSP chain which had been set up with before. + + The plugin handle (returned by ). + , if successfully removed, else . Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe is not a valid plugin handle. + + + + + + + Invokes the internal 'ModifySamples' method of the Winamp DSP directly (which is only needed for user defined callbacks). + + The plugin handle (returned by ). + The IntPtr to the memory block containing the sample data to modify. + The number of bytes contained in the buffer. + The number of bytes modified, which should always be the number of bytes specified when calling this method. Or 0, if an error occured. + This method can and should only be used with those Winamp DSPs which return exactly as much samples as provided - meaning not modifying the samplerate, tempo, pitch etc.! + This method can be used with 8-bit, 16-bit or float channels. Since all Winamp DSPs will internally only work with 16-bit channels an automatic internal conversion from 8-bit resp. float to 16-bit and back will take place. + + + + private int _streamA = 0; + private int _dspPluginA = 0; + private DSPPROC _myDSPAddr; + ... + _dspPluginA = BassWaDsp.BASS_WADSP_Load("dsp_test.dll", 5, 5, 100, 100, null); + BassWaDsp.BASS_WADSP_Start(_dspPluginA, 0, 0); + ... + _streamA = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, + BASSFlag.BASS_DEFAULT | BASSFlag.BASS_STREAM_AUTOFREE); + // play the stream + if (_streamA != 0 ) + { + _myDSPAddr = new DSPPROC(MyWinampDSP); + Bass.BASS_ChannelSetDSP(_streamA, _myDSPAddr, new IntPtr(_dspPluginA), -500); + BassWaDsp.BASS_WADSP_SetChannel(_dspPluginA, _streamA); + Bass.BASS_ChannelPlay(_streamA, false); + } + ... + private void MyWinampDSP(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + if (length == 0 || buffer == IntPtr.Zero) + return; + BassWaDsp.BASS_WADSP_ModifySamplesDSP(user.ToInt32(), buffer, length); + } + + + Private _streamA As Integer = 0 + Private _dspPluginA As Integer = 0 + Private _myDSPAddr As DSPPROC + ... + _dspPluginA = BassWaDsp.BASS_WADSP_Load("dsp_test.dll", 5, 5, 100, 100, Nothing) + BassWaDsp.BASS_WADSP_Start(_dspPluginA, 0, 0) + ... + _streamA = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, + BASSFlag.BASS_DEFAULT Or BASSFlag.BASS_STREAM_AUTOFREE) + ' play the stream + If _streamA <> 0 Then + _myDSPAddr = New DSPPROC(AddressOf MyWinampDSP) + Bass.BASS_ChannelSetDSP(_streamA, _myDSPAddr, New IntPtr(_dspPluginA), - 500) + BassWaDsp.BASS_WADSP_SetChannel(_dspPluginA, _streamA) + Bass.BASS_ChannelPlay(_streamA, False) + End If + ... + Private Sub MyWinampDSP(handle As Integer, channel As Integer, + buffer As IntPtr, length As Integer, user As IntPtr) + If length = 0 OrElse buffer = IntPtr.Zero Then + Return + End If + BassWaDsp.BASS_WADSP_ModifySamplesDSP(user.ToInt32(), buffer, length) + End Sub + + + + + + Invokes the internal 'ModifySamples' method of the Winamp DSP directly (which is only needed for user defined callbacks). + + The plugin handle (returned by ). + The array of byte values containing the sample data to modify. + The number of bytes contained in the buffer. + The number of bytes modified, which should always be the number of bytes specified when calling this method. Or 0, if an error occured. + This method can and should only be used with those Winamp DSPs which return exactly as much samples as provided - meaning not modifying the samplerate, tempo, pitch etc.! + This method can be used with 8-bit, 16-bit or float channels. Since all Winamp DSPs will internally only work with 16-bit channels an automatic internal conversion from 8-bit resp. float to 16-bit and back will take place. + + + + + Invokes the internal 'ModifySamples' method of the Winamp DSP directly (which is only needed for user defined callbacks). + + The plugin handle (returned by ). + The array of Int16 values containing the sample data to modify. + The number of bytes contained in the buffer. + The number of bytes modified, which should always be the number of bytes specified when calling this method. Or 0, if an error occured. + This method can and should only be used with those Winamp DSPs which return exactly as much samples as provided - meaning not modifying the samplerate, tempo, pitch etc.! + This method can be used with 8-bit, 16-bit or float channels. Since all Winamp DSPs will internally only work with 16-bit channels an automatic internal conversion from 8-bit resp. float to 16-bit and back will take place. + + + + + Invokes the internal 'ModifySamples' method of the Winamp DSP directly (which is only needed for user defined callbacks). + + The plugin handle (returned by ). + The array of Int32 values containing the sample data to modify. + The number of bytes contained in the buffer. + The number of bytes modified, which should always be the number of bytes specified when calling this method. Or 0, if an error occured. + This method can and should only be used with those Winamp DSPs which return exactly as much samples as provided - meaning not modifying the samplerate, tempo, pitch etc.! + This method can be used with 8-bit, 16-bit or float channels. Since all Winamp DSPs will internally only work with 16-bit channels an automatic internal conversion from 8-bit resp. float to 16-bit and back will take place. + + + + + Invokes the internal 'ModifySamples' method of the Winamp DSP directly (which is only needed for user defined callbacks). + + The plugin handle (returned by ). + The array of float values containing the sample data to modify. + The number of bytes contained in the buffer. + The number of bytes modified, which should always be the number of bytes specified when calling this method. Or 0, if an error occured. + This method can and should only be used with those Winamp DSPs which return exactly as much samples as provided - meaning not modifying the samplerate, tempo, pitch etc.! + This method can be used with 8-bit, 16-bit or float channels. Since all Winamp DSPs will internally only work with 16-bit channels an automatic internal conversion from 8-bit resp. float to 16-bit and back will take place. + + + + + Invokes the internal 'ModifySamples' method of the Winamp DSP directly (which is only needed for user defined callbacks or in a user defined ). + + The plugin handle (returned by ). + The pointer to the memory block containing the sample data to modify. + The number of bytes contained in the buffer. + The number of bytes modified, which might be different from the number of bytes given. + A Winamp DSP might return at max. twice the number of bytes but not less than half the number of bytes. + This method can be used to support Winamp DSPs which modify the samplerate, pitch etc. - meaning modifying the number of bytes given. + However, this is not a simple task to do so, since Bass does not expect this. In order to handle a modified number of bytes you might need to implement a complex intermediate 'ring-buffer' in between Bass and the Winamp DSP. + Note: Some Winamp DSPs work with a fixed number of 1152 samples only (meaning 1152 * chans * 2 bytes!) - this might also bring in some additional complexity. + Implementing and correctly handling this intermediate 'buffer' is up to you and not handled by BASS_WADSP - however, this method is the right method to use for such a case, since it returns exactly what the Winamp DSP returned. + So make sure, that the buffer is at least twice as big as the samples it contains when you call this method, so that the Winamp DSP might have enough space to store it's returned samples into it. + This method can be used with 8-bit, 16-bit or float channels. Since all Winamp DSPs will internally only work with 16-bit channels an automatic internal conversion from 8-bit resp. float to 16-bit and back will take place. + + + + + Invokes the internal 'ModifySamples' method of the Winamp DSP directly (which is only needed for user defined callbacks or in a user defined ). + + The plugin handle (returned by ). + The array of byte values containing the sample data to modify. + The number of bytes contained in the buffer. + The number of bytes modified, which might be different from the number of bytes given. + A Winamp DSP might return at max. twice the number of bytes but not less than half the number of bytes. + This method can be used to support Winamp DSPs which modify the samplerate, pitch etc. - meaning modifying the number of bytes given. + However, this is not a simple task to do so, since Bass does not expect this. In order to handle a modified number of bytes you might need to implement a complex intermediate 'ring-buffer' in between Bass and the Winamp DSP. + Note: Some Winamp DSPs work with a fixed number of 1152 samples only (meaning 1152 * chans * 2 bytes!) - this might also bring in some additional complexity. + Implementing and correctly handling this intermediate 'buffer' is up to you and not handled by BASS_WADSP - however, this method is the right method to use for such a case, since it returns exactly what the Winamp DSP returned. + So make sure, that the buffer is at least twice as big as the samples it contains when you call this method, so that the Winamp DSP might have enough space to store it's returned samples into it. + This method can be used with 8-bit, 16-bit or float channels. Since all Winamp DSPs will internally only work with 16-bit channels an automatic internal conversion from 8-bit resp. float to 16-bit and back will take place. + + + + + Invokes the internal 'ModifySamples' method of the Winamp DSP directly (which is only needed for user defined callbacks or in a user defined ). + + The plugin handle (returned by ). + The array of Int16 values containing the sample data to modify. + The number of bytes contained in the buffer. + The number of bytes modified, which might be different from the number of bytes given. + A Winamp DSP might return at max. twice the number of bytes but not less than half the number of bytes. + This method can be used to support Winamp DSPs which modify the samplerate, pitch etc. - meaning modifying the number of bytes given. + However, this is not a simple task to do so, since Bass does not expect this. In order to handle a modified number of bytes you might need to implement a complex intermediate 'ring-buffer' in between Bass and the Winamp DSP. + Note: Some Winamp DSPs work with a fixed number of 1152 samples only (meaning 1152 * chans * 2 bytes!) - this might also bring in some additional complexity. + Implementing and correctly handling this intermediate 'buffer' is up to you and not handled by BASS_WADSP - however, this method is the right method to use for such a case, since it returns exactly what the Winamp DSP returned. + So make sure, that the buffer is at least twice as big as the samples it contains when you call this method, so that the Winamp DSP might have enough space to store it's returned samples into it. + This method can be used with 8-bit, 16-bit or float channels. Since all Winamp DSPs will internally only work with 16-bit channels an automatic internal conversion from 8-bit resp. float to 16-bit and back will take place. + + + + + Invokes the internal 'ModifySamples' method of the Winamp DSP directly (which is only needed for user defined callbacks or in a user defined ). + + The plugin handle (returned by ). + The array of Int32 values containing the sample data to modify. + The number of bytes contained in the buffer. + The number of bytes modified, which might be different from the number of bytes given. + A Winamp DSP might return at max. twice the number of bytes but not less than half the number of bytes. + This method can be used to support Winamp DSPs which modify the samplerate, pitch etc. - meaning modifying the number of bytes given. + However, this is not a simple task to do so, since Bass does not expect this. In order to handle a modified number of bytes you might need to implement a complex intermediate 'ring-buffer' in between Bass and the Winamp DSP. + Note: Some Winamp DSPs work with a fixed number of 1152 samples only (meaning 1152 * chans * 2 bytes!) - this might also bring in some additional complexity. + Implementing and correctly handling this intermediate 'buffer' is up to you and not handled by BASS_WADSP - however, this method is the right method to use for such a case, since it returns exactly what the Winamp DSP returned. + So make sure, that the buffer is at least twice as big as the samples it contains when you call this method, so that the Winamp DSP might have enough space to store it's returned samples into it. + This method can be used with 8-bit, 16-bit or float channels. Since all Winamp DSPs will internally only work with 16-bit channels an automatic internal conversion from 8-bit resp. float to 16-bit and back will take place. + + + + + Invokes the internal 'ModifySamples' method of the Winamp DSP directly (which is only needed for user defined callbacks or in a user defined ). + + The plugin handle (returned by ). + The array of float values containing the sample data to modify. + The number of bytes contained in the buffer. + The number of bytes modified, which might be different from the number of bytes given. + A Winamp DSP might return at max. twice the number of bytes but not less than half the number of bytes. + This method can be used to support Winamp DSPs which modify the samplerate, pitch etc. - meaning modifying the number of bytes given. + However, this is not a simple task to do so, since Bass does not expect this. In order to handle a modified number of bytes you might need to implement a complex intermediate 'ring-buffer' in between Bass and the Winamp DSP. + Note: Some Winamp DSPs work with a fixed number of 1152 samples only (meaning 1152 * chans * 2 bytes!) - this might also bring in some additional complexity. + Implementing and correctly handling this intermediate 'buffer' is up to you and not handled by BASS_WADSP - however, this method is the right method to use for such a case, since it returns exactly what the Winamp DSP returned. + So make sure, that the buffer is at least twice as big as the samples it contains when you call this method, so that the Winamp DSP might have enough space to store it's returned samples into it. + This method can be used with 8-bit, 16-bit or float channels. Since all Winamp DSPs will internally only work with 16-bit channels an automatic internal conversion from 8-bit resp. float to 16-bit and back will take place. + + + + + + + + + + + + Returns the name of the loaded Winamp DSP plugin. + + The plugin handle (returned by ). + The name of the plugin on success or on error. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe is not a valid plugin handle. + + + + + + + Returns the number of modules contained in the loaded Winamp DSP. + + The plugin handle (returned by ). + The number of available modules or -1 if an error occured. Use to get the error code. + Winamp DSPs might implement multiple different modules within the same DSP plugin. + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe is not a valid plugin handle. + + + + + + + + + + + + + + + Returns the name of a certain module of a loaded Winamp DSP. + + The plugin handle (returned by ). + The module number to get the name from (the first module is 0). + The name of the module on success or on error (or if no module with that number exists). Use to get the error code. + Winamp DSPs might provide multiple independent modules. You might get the number of available modules with . + However, you can only start one module at a time for a certain Winamp DSP. + You can use this method in a setup dialog to list all the available modules of a Winamp DSP. + + + ERROR CODEDescription + BASS_ERROR_HANDLEThe is not a valid plugin handle. + BASS_ERROR_ILLPARAMThe number is invalid. + + + + + + string name; + for (int n=0; (name = BassWaDsp.BASS_WADSP_GetModuleName(plugin, n)) != null; n++) + { + Console.WriteLine(name); + } + + + Dim n As Integer = 0 + Dim name As String = "" + While Not (name Is Nothing) + name = BassWaDsp.BASS_WADSP_GetModuleName(plugin, n) + n += 1 + If Not (name Is Nothing) Then + Console.WriteLine(name) + End If + End While + + + + + + Returns an array of strings containing all module names of a Winamp DSP. + + The plugin handle (returned by ). + All names of all modules contained in the Winamp DSP. + You can use this method in a setup dialog to list all the available modules of a Winamp DSP. + + + + + Free the temporary plugin info resources. + + on success, else . Use to get the error code. + Should and must be called after when the plugin info is not needed anymore. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been called. + + + + + + + Loads a Winamp DSP library into the temporary plugin info workspace. + + The fully qualified path and name of the Winamp DSP library you want to load (e.g. "C:\\Program Files\\Winamp\\Plugins\\dsp_ss.dll"). + Both Unicode as well as Ansi filenames are supported, whereas Unicode is tried first. + on success, else . Use to get the error code. + The temporary plugin info workspace can be used to retrieve general information about a Winamp DSP without starting it. + This method will be used in the same way is used. + The BASS.NET API offers an additional helper class which internally uses the temporary plugin info workspace and makes it obsolete to use this method directly. + NOTE: Do not use this method while you have already loaded the same Winamp plugin (e.g. via ) as this might result in any unexpected behavior, since some Winamp plugins might crash when they are loaded twice. + + + ERROR CODEDescription + BASS_ERROR_FILEOPENThe can not be found or loaded. + BASS_ERROR_FILEFORMThe doesn't seem to be a Winamp DSP library file. + + + + + + + + + + + + + Returns the name of the Winamp DSP plugin which has been loaded into the temporary plugin info workspace. + + The name of the plugin on success or on error. Use to get the error code. + The BASS.NET API offers an additional helper class which internally uses the temporary plugin info workspace and makes it obsolete to use these methods directly. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been called. + + + + + + + Returns the number of modules contained in the Winamp DSP which has been loaded into the temporary plugin info workspace. + + The number of available modules or -1 if an error occured. Use to get the error code. + Winamp DSPs might implement multiple different modules within the same DSP plugin. + The BASS.NET API offers an additional helper class which internally uses the temporary plugin info workspace and makes it obsolete to use these methods directly. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been called. + + + + + + + + + + + + + + Returns the name of a certain module of a Winamp DSP which has been loaded into the temporary plugin info workspace. + + The module number to get the name from (the first module is 0). + The name of the module on success or on error (or if no module with that number exists). Use to get the error code. + Winamp DSPs might provide multiple independent modules. You might get the number of available modules with . + You can use this method in a setup dialog to list all the available modules of a Winamp DSP. + The BASS.NET API offers an additional helper class which internally uses the temporary plugin info workspace and makes it obsolete to use these methods directly. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been called. + BASS_ERROR_ILLPARAMThe number is invalid. + + + + + + string name; + for (int n=0; (name = BassWaDsp.BASS_WADSP_PluginInfoGetModuleName(n)) != null; n++) + { + Console.WriteLine(name); + } + + + Dim n As Integer = 0 + Dim name As String = "" + While Not (name Is Nothing) + name = BassWaDsp.BASS_WADSP_PluginInfoGetModuleName(n) + n += 1 + If Not (name Is Nothing) Then + Console.WriteLine(name) + End If + End While + + + + + + Returns an array of strings containing all module names of a Winamp DSP which has been loaded into the temporary plugin info workspace. + + All names of all modules contained in the Winamp DSP. + You can use this method in a setup dialog to list all the available modules of a Winamp DSP. + The BASS.NET API offers an additional helper class which internally uses the temporary plugin info workspace and makes it obsolete to use these methods directly. + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + Communication to Winamp is done via the classic Win32 Message API. Most DSP plugins use this to ask for certain values. + These definitions are the most commonly used messages, which might be handled by the fake winamp window which we create. + + + + + IPC_GETOUTPUTTIME returns the position in milliseconds of the current song (mode = 0), + or the song length, in seconds (mode = 1).Returns -1 if not playing or error. + int res = SendMessage(hwnd_winamp,WM_WA_IPC,mode,IPC_GETOUTPUTTIME); + + + + + IPC_ISPLAYING returns the status of playback. + If it returns 1, it is playing. if it returns 3, it is paused, if it returns 0, it is not playing. + int res = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISPLAYING); + + + + + Version will be 0x20yx for winamp 2.yx. + Versions previous to Winamp 2.0 typically use 0x1zyx for 1.zx versions. Weird, I know. + int version = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVERSION); + + + + + Using IPC_STARTPLAY is like hitting 'Play' in Winamp, mostly. + SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_STARTPLAY); + + + + + IPC_GETINFO returns info about the current playing song. The value it returns depends on the value of 'mode' (wParam): + + ModeMeaning + 0Samplerate (i.e. 44100) + 1Bitrate (i.e. 128) + 2Channels (i.e. 2) + + int inf=SendMessage(hwnd_winamp,WM_WA_IPC,mode,IPC_GETINFO); + + + + + IPC_GETLISTLENGTH returns the length of the current playlist, in tracks. + int length = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTLENGTH); + + + + + IPC_GETLISTPOS returns the playlist position [index]. + int pos=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS); + + + + + IPC_GETPLAYLISTFILE gets the filename of the playlist entry [index]. Returns a pointer to it. Returns on error. + char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTFILE); + + + + + IPC_GETPLAYLISTTITLE gets the title of the playlist entry [index]. Returns a pointer to it. Returns on error. + char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTTITLE); + + + + + Is defined as Win32's WM_USER an. When a message of this value arrives, we know, that we might handle it by ourself. + + + + + General helper class to retrieve information about a Winamp DSP. + + + + + Prevent this constructor from being visible. + + + + + Default constructor initialising and retrieving information about a Winamp DSP. + + The fully qualified path and name of the file to be constructed. + + + + Loads the Winamp DSP plugin. + + on success, else . + Make sure to call when you don't need it anymore in order to unload and free the plugin. + + + + Unloads the Winamp DSP plugin. + + on success, else . + This must be called once you are done with the DSP to free all resources. + If the DSP is already started it will also be stopped. + + + + Starts a certain module of a Wianmp DSP plugin and assignes it to a channel as a new DSP. + + The module index to start (must be between 0 and -1). + The BASS stream channel handle to assign it to. + The DSP priority to use when assigning the DSP. + The DSP handle on success - else 0 is returned. + + The Winamp DSP must have been loaded with before you can use this method! + Call if you don't need this module anymore and to remove the DSP from the channel. + + + + + Stops the currently started Winamp DSP plugin module. + + on success, else . + Make sure to call this method once you ed it. + + + + Sets a global song title for the loaded and started Winamp DSP. + + The song title to set. + on success, else . + + Some Winamp DSPs require or simply display a current song title. Use this method to set this song title. + It will then be used in the internal Window message handler for all fake Winamp windows. + In most cases it is not required to set any song title at all. + For streaming DSPs (e.g. SHOUTcast Source DSP) use this function to set the title metadata. + + + + + Sets a global song title for the loaded and started Winamp DSP. + + The song title to set. + on success, else . + + Some Winamp DSPs require or simply display a current playing file name. Use this method to set this file name. + It will then be used in the internal Window message handler for all fake Winamp windows. + In most cases it is not required to set any file name at all. + + + + + Shows the Winamp DSP config dialog. + + on success, else . + The Winamp DSP must have been loaded and started. + + + + A description of the Winamp DSP info object (description - filename). + + A description of the Winamp DSP info object (description - filename). + + + + Finds all Winamp DSP plugins contained in a given directory and stores all related information in the list. + + The directory in which to search for Winamp DSP plugins. + Using this method subsequently is allowed and ensures, that new Winamp plugins can be loaded and already loaded Winamp plugins are not loaded twice. + Use the property to access all found Winamp DSP plugins. + Note, that when calling this method multiple times only newly found Winamp plugins are added to the list, already existing plugins will not be loaded or rescanned again. + + + + WINAMP_DSP.FindPlugins("C:\\Program Files\\Winamp\\Plugins"); + this.listBox1.Items.AddRange(WINAMP_DSP.PlugIns); + ... + // and display all modules out of a certain dsp... + WINAMP_DSP dsp = (WINAMP_DSP)this.listBox1.SelectedItem; + if (dsp.modulecount > 0) + { + // display all modules + this.comboBox1.Items.Clear(); + this.comboBox1.Items.AddRange(dsp.modulenames); + this.comboBox1.SelectedIndex = 0; + } + + + WINAMP_DSP.BASS_WADSP_FindPlugins("C:\Program Files\Winamp\Plugins") + Me.listBox1.Items.AddRange(WINAMP_DSP.PlugIns) + ... + ' and display all modules out of a certain dsp... + Dim dsp As WINAMP_DSP = CType(Me.listBox1.SelectedItem, WINAMP_DSP) + If dsp.modulecount > 0 Then + ' display all modules + Me.comboBox1.Items.Clear() + Me.comboBox1.Items.AddRange(dsp.modulenames) + Me.comboBox1.SelectedIndex = 0 + End If + + + + + + Gets the fully qualified path and name of the Winamp DSP file. + + + + + Gets the description of the Winamp DSP. + + + + + Gets the number of modules contained in this Winamp DSP. + + + + + Gets an array of available module names. + + + + + Is the Winamp DSP plugin already loaded? + + + + + Is the Winamp DSP plugin already started and assigned to a channel? + + + + + Returns the currently selected and started module index - or -1 if no module is started. + + + + + Gets the list of available Winamp DSPs (as loaded by ). + + + + + User defined Window Message Process Handler (to be used with ). + Normally this is not needed, since BASS_WADSP implements a default handler which emulates most functions needed by Winamp DSPs. + However, some very special Winamp DSPs might require something special. So you might implement your own windows message handler here. + + The Window handle we are dealing with - which is the hidden fake window which BASS_WADSP has created during and which emulates a Winamp 1.x class. + The window message send. You typically might only react on WM_USER messages (also defined as ). + The wParam message parameter see the Winamp SDK for further details. + The lParam message parameter see the Winamp SDK for further details. + See the Winamp SDK documentation for information. + + The enumeration defines all lParam values which you should typically handle. See the Winamp SDK for further details. + + + + + BASS.NET API wrapper for BASS_SPX.DLL + Requires: bass_spx.dll - Speex Audio Codec (SPX) Add-On - available @ www.un4seen.com. + + + BASS_SPX is an extension to the BASS audio library, enabling the playback of Speex files. + Speex is an open source and patent-free audio compression format designed for speech. The Speex Project aims to lower the barrier of entry for voice applications by providing a free alternative to expensive proprietary speech codecs. + Moreover, Speex is well-adapted to Internet applications and provides useful features that are not present in most other codecs. + The Speex format is used in the same way as any of the built-in BASS stream formats. Simply call to load the add-on into BASS and benefit the usage of the standard sample/stream/URL/user functions, or call the /URL/User functions. + More information can be found on www.speex.org. + + + + + NOT used - all members are static! + + + + + + + + + + + + + + + + Creates a sample stream from a Speex Audio file. + This overload implements UNICODE filenames. The BASS_UNICODE flag will be added automatically, since all .Net strings are always unicode. + + Filename for which a stream should be created. + File offset to begin streaming from. + Data length... 0 = use all data up to the end of the file. + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + + + + + + + + + + + + Creates a sample stream from a Speex Audio memory IntPtr. + This overload implements streaming from memory. + + An unmanaged pointer to the memory location as an IntPtr. + Offset to begin streaming from (unused for memory streams, set to 0). + Data length (needs to be set to the length of the memory streams in bytes which should be played). + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + Creates a sample stream from a Speex Audio file via a user callback function. + + File system to use: see . + Any combination of these flags: see . + The user defined file functions (see ). + User instance data to pass to the callback functions. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + See . + + + + + + + + + + + + + + + + + + + + + + + + + + Creates a sample stream from a Speex Audio file on the internet, optionally receiving the downloaded data in a callback. + + URL of the file to stream. Should begin with "http://" or "ftp://". + File position to start streaming from. This is ignored by some servers, specifically when the file length is unknown. + Any combination of these flags: see . + Callback function to receive the file as it is downloaded... = no callback. + User instance data to pass to the callback function. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + Supported file extensions of the bass_spx.dll + + + + + Supported file format name of the bass_spx.dll + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + The disadvantage of this method is, that the standard plugin support for is not working - so you would need to use the native add-on methods! + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + BASS.NET API wrapper for BASS_OFR.DLL + Requires: bass_ofr.dll and OptimFROG.dll - OptimFROG and OptimFROG DualStream Audio Codec (OFR) Add-On - available @ www.un4seen.com. + + + BASS_OFR is an extension to the BASS audio library, enabling the playback of OptimFROG and OptimFROG DualStream files. + OptimFROG is a lossless audio compression program. Its main goal is to reduce the size of audio files, while permitting bit identical restoration of all input. + OptimFROG DualStream is aimed at filling the big gap between perceptual coding and lossless coding. The goal is to offer real transparent audio coding at half or less the bitrate generally used by lossless coding, + and also to permit progressive consistent increase of the quality level, until lossless coding is reached. + The OptimFROG format is used in the same way as any of the built-in BASS stream formats. Simply call to load the add-on into BASS and benefit the usage of the standard sample/stream/user functions, or call the /User functions. + More information can be found on www.losslessaudio.org. + + + + + NOT used - all members are static! + + + + + + + + + + + + + + + + Creates a sample stream from a OptimFROG or OptimFROG DualStream file. + This overload implements Unicode filenames. The BASS_UNICODE flag will be added automatically. + + Filename for which a stream should be created. + File offset to begin streaming from. + Data length... 0 = use all data up to the end of the file. + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + + + + + + + + + + + + Creates a sample stream from a OptimFROG or OptimFROG DualStream memory IntPtr. + This overload implements streaming from memory. + + An unmanaged pointer to the memory location as an IntPtr. + Offset to begin streaming from (unused for memory streams, set to 0). + Data length (needs to be set to the length of the memory streams in bytes which should be played). + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + Creates a sample stream from a OptimFROG or OptimFROG DualStream file via a user callback function. + + File system to use: see . + Any combination of these flags: see . + The user defined file functions (see ). + User instance data to pass to the callback functions. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + See . + + + + Supported file extensions of the bass_ofr.dll + + + + + Supported file format name of the bass_ofr.dll + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + The disadvantage of this method is, that the standard plugin support for is not working - so you would need to use the native add-on methods! + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + BASS.NET API wrapper for BASS_DSHOW.DLL + Requires: BASS_DSHOW.dll - DirectShow/Video support Add-On - available @ www.un4seen.com. + + + BASS_DSHOW/xVideo is an extention to the BASS audio library, providing a set of functions for rendering direct show audio and video content. + + + + + Current BASS_DSHOW version (without minor revision). + + + + + NOT used - all members are static! + + + + + Retrieves the version number of the BASS_DSHOW.DLL that is loaded. + + The BASS_DSHOW version. For example, 0x02040103 (hex), would be version 2.4.1.3. + There is no guarantee that a previous or future version of BASS_DSHOW supports all the BASS_DSHOW functions that you are using, so you should always use this function to make sure the correct version is loaded. + It is safe to assume that future minor revisions (indicated in the LOWORD) will be fully compatible. + You might use the global constant to check the major revision. + Note: Calling this method will also automatically load the library into memory. + + + Checking the major version only: + + if ( Utils.HighWord(BassDShow.BASS_DSHOW_GetVersion()) != BassDShow.BASSDSHOWVERSION ) + { + MessageBox.Show(this, "Wrong BassDShow Version!"); + } + + + If Utils.HighWord(BassDShow.BASS_DSHOW_GetVersion()) <> BassDShow.BASSDSHOWVERSION Then + MessageBox.Show(Me, "Wrong BassDShow Version!") + End If + + Checking for full version "2.4.1.3": + + if (BassDShow.BASS_DSHOW_GetVersion() < Utils.MakeLong(0x0103, 0x0204)) + { + MessageBox.Show(this, "Wrong BassDShow Version!"); + } + + + If BassDShow.BASS_DSHOW_GetVersion() < Utils.MakeLong(&H103, &H204) Then + MessageBox.Show(Me, "Wrong BassDShow Version!") + End If + + + + + + Retrieves the version of the BASS_DSHOW.DLL that is loaded. + + The number of components to use. The fieldCount ranges from 1 to 4 (major.minor.build.revision). + The BASS_DSHOW version (major.minor.build.revision). + There is no guarantee that a previous or future version of BASS_DSHOW supports all the BASS_DSHOW functions that you are using, so you should always use this function to make sure the correct version is loaded. + It is safe to assume that future minor revisions (indicated in the LOWORD) will be fully compatible. + Note: Calling this method will also automatically load the library into memory. + + + + Version expectedVersion = new Version(2, 4); + if (BassDShow.BASS_DSHOW_GetVersion(2) < expectedVersion) + { + MessageBox.Show( this, "Wrong BassDShow Version!" ); + } + + + Dim expectedVersion As New Version(2, 4) + If BassDShow.BASS_DSHOW_GetVersion(2) < expectedVersion Then + MessageBox.Show(Me, "Wrong BassDShow Version!") + End If + + + + + + Retrieves the error code for the most recent BASS_DSHOW function call. + + If no error occured during the last BASS_DSHOW function call then BASS_DSHOW_OK is returned, else one of the values is returned. + See the function description for an explanation of what the error code means. + + + + + + + + + + + + Initialize the DSHOW library. This will initialize the library for use. + + The application's main window or 0 = the current foreground window (use this for console applications). + Any combination of these flags (see ): + + BASS_DSHOW_DefaultNormal mode. + BASS_DSHOW_MultiThreadEnable multithread mode. + + + If an error occurred then is returned, else is returned (use to get the error code). + Call this method prior to any other BASS_DSHOW methods. + + + + + Frees all resources used by DSHOW, including all it's streams. + + If an error occurred then is returned, else is returned (use to get the error code). + This function will also free all streams created by BASS_DSHOW. + + + + + + + + + + + + + + Creates a sample stream from a supported file. + + The filename to render. + The position to begin playing from. + An initial window handle (can be ). + Any combination of these flags : + + BASS_DSHOW_STREAM_MIXUse this flag to enable mixing video on a channel. + BASS_DSHOW_NOAUDIO_PROCUse this flag to disable audio processing. + BASS_DSHOW_STREAM_LOOPUse this flag to auto restart the stream after it's finish. + BASS_DSHOW_STREAM_VIDEOPROCUse this to enable video processor. + BASS_DSHOW_STREAM_AUTODVDUse this flag to enable auto dvd functions(on mouse down, keys etc). + BASS_STREAM_AUTOFREEAutomatically free the stream when it ends. This allows you to stream a file and forget about it, as BASS will automatically free the stream's resources when it has reached the end or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_UNICODEfile is a Unicode (16-bit characters) filename (automatically set with this overload). + + + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + The necesary codec to decode the video must be available! + When a start position is specified and the requested position is not available, playback it will start automaticaly from the begginning. + + + + + Creates a sample stream from memory data. + + An unmanaged pointer to the memory location as an IntPtr. + Data length (needs to be set to the length of the memory stream in bytes which should be played). + An initial window handle (can be ). + Any combination of these flags : + + BASS_DSHOW_STREAM_MIXUse this flag to enable mixing video on a channel. + BASS_DSHOW_NOAUDIO_PROCUse this flag to disable audio processing. + BASS_DSHOW_STREAM_LOOPUse this flag to auto restart the stream after it's finish. + BASS_DSHOW_STREAM_VIDEOPROCUse this to enable video processor. + BASS_DSHOW_STREAM_AUTODVDUse this flag to enable auto dvd functions(on mouse down, keys etc). + BASS_STREAM_AUTOFREEAutomatically free the stream when it ends. This allows you to stream a file and forget about it, as BASS will automatically free the stream's resources when it has reached the end or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_UNICODEfile is a Unicode (16-bit characters) filename (automatically set with this overload). + + + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + The necesary codec to decode the video must be available! + + + + + + + Any combination of these flags : + + BASS_DSHOW_STREAM_MIXUse this flag to enable mixing video on a channel. + BASS_DSHOW_NOAUDIO_PROCUse this flag to disable audio processing. + BASS_DSHOW_STREAM_LOOPUse this flag to auto restart the stream after it's finish. + BASS_DSHOW_STREAM_VIDEOPROCUse this to enable video processor. + BASS_DSHOW_STREAM_AUTODVDUse this flag to enable auto dvd functions(on mouse down, keys etc). + BASS_STREAM_AUTOFREEAutomatically free the stream when it ends. This allows you to stream a file and forget about it, as BASS will automatically free the stream's resources when it has reached the end or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_UNICODEfile is a Unicode (16-bit characters) filename (automatically set with this overload). + + + An initial window handle (can be ). + The user defined file function (see ). + User instance data to pass to the callback functions. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + The necesary codec to decode the video must be available! + + + + + + + + + + + + + + + Creates a sample stream from a supported file using a given filter. + + The filename to render. + The CLSID/GUID string of the filter to use (e.g. "{55DA30FC-F16B-49FC-BAA5-AE59FC65F82D}"). + An initial window handle (can be ). + Any combination of these flags : + + BASS_DSHOW_STREAM_MIXUse this flag to enable mixing video on a channel. + BASS_DSHOW_NOAUDIO_PROCUse this flag to disable audio processing. + BASS_DSHOW_STREAM_AUTODVDUse this flag to enable auto dvd functions(on mouse down, keys etc). + BASS_STREAM_AUTOFREEAutomatically free the stream when it ends. This allows you to stream a file and forget about it, as BASS will automatically free the stream's resources when it has reached the end or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_UNICODEfile is a Unicode (16-bit characters) filename (automatically set with this overload). + + + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + The necesary codec to decode the video must be available! + + + + + Sets the playback position of a video stream. + + The video channel handle (as returned by ). + The new position to set. + How to retrieve the position. One of the following (see ): + + BASS_DSHOW_POS_SECThe position is in seconds. + BASS_DSHOW_POS_MILISECThe position is in milliseconds. + BASS_DSHOW_POS_FRAMEThe position is in video frames. + BASS_DSHOW_POS_REFTIMEThe position is in reference time (1 unit = 100 nanoseconds). + + + + + + Gets the current position of the video stream. + + The video channel handle (as returned by ). + How to get the position. One of the following (see ): + + BASS_DSHOW_POS_SECThe position is in seconds. + BASS_DSHOW_POS_MILISECThe position is in milliseconds. + BASS_DSHOW_POS_FRAMEThe position is in video frames. + BASS_DSHOW_POS_REFTIMEThe position is in reference time (1 unit = 100 nanoseconds). + + + If successful, the current position of the video stream in units according to the used, + else 0 is returned. Use to get the error code. + + + + Gets the length of the video stream. + + The video channel handle (as returned by ). + How to get the position. One of the following (see ): + + BASS_DSHOW_POS_SECThe length is in seconds. + BASS_DSHOW_POS_MILISECThe length is in milliseconds. + BASS_DSHOW_POS_FRAMEThe length is in video frames. + BASS_DSHOW_POS_REFTIMEThe length is in reference time (1 unit = 100 nanoseconds). + + + If successful, the length of the video stream in units according to the used, + else 0 is returned. Use to get the error code. + 0 is ussualy returned when the stream doesn't contain video or if an invalid channel handle was specified. + + + + Starts playback of a video stream. + + The video channel handle (as returned by ). + If an error occurred then is returned, else is returned (use to get the error code). + + + + Pauses playback of a video stream. + + The video channel handle (as returned by ). + If an error occurred then is returned, else is returned (use to get the error code). + + + + Stops playback of a video stream. + + The video channel handle (as returned by ). + If an error occurred then is returned, else is returned (use to get the error code). + + + + Frees all resources of a video stream. + + The video channel handle (as returned by ). + If an error occurred then is returned, else is returned (use to get the error code). + + + + Retrieves information on a video channel. + + The video channel handle (as returned by ). + instance where to store the channel information at. + + + + Retrieves information on a video channel. + + The video channel handle (as returned by ). + A instance containing the video info. + + + + Adds a new Video Window to the channel. + + The video channel handle (as returned by ). + A valid window handle. + If successful, the new video window handle is returned, else 0 is returned. Use to get the error code. + + You can use this function to a new video window to a channel. + Adding new windows depends on the hardware capabilities (adding many new windows might result in a high CPU usage). + You can use the function to remove an added video window. + + + + + Removes an added video window from the channel. + + The video channel handle (as returned by ). + A valid window handle (as returned by ) to remove. + If an error occurred then is returned, else is returned (use to get the error code). + + + + Resizes the rendering of a video stream to a new size. + + The video channel handle (as returned by ). + A valid window handle (as returned by ) to resize or 0(zero) for the main video window. + The left coordinate. + The top coordinate. + The right coordinate. + The bottom coordinate. + + + + Toggles the rendering of a video stream between full screen (on/off). + + The video channel handle (as returned by ). + to toggle the rendering to full screen - to turn full screen rendering off. + + + + Sets s video window handle. + + The video channel handle (as returned by ). + A valid window handle (as returned by ) or 0 for the main video window. + A valid window handle. + + + + Sets a BASS_DSHOW configuration option. + + The option to set (one of the values). + The value to use. + See the values to know what parameters apply to . + Options: + + BASS_DSHOW_CONFIG_VideoRendererSets the video renderer to use. + renderer (int): One of the following values: + BASS_DSHOW_VMR7 : pass this to select the VMR7 windowed renderer. + BASS_DSHOW_VMR9 : pass this to select the VMR9 windowed renderer. + BASS_DSHOW_VMR7WindowsLess : pass this to select the VMR7 window less renderer. + BASS_DSHOW_VMR9WindowsLess : pass this to select the VMR9 window less renderer. + BASS_DSHOW_EVR : pass this to select the Enhanced video renderer. + BASS_DSHOW_NULLVideo : pass this to select the NULL video renderer. + + BASS_DSHOW_CONFIG_WindowLessHandleBASS_DSHOW needs an initial window handle when using windowsless renderers, so the value parameter should be a valid window handle. + hwnd (int): a valid window handle to be used with the window less mode. + + BASS_DSHOW_CONFIG_WindowLessStreamsSets the number of streams when using windows less mode. + number (int): between 1 and 15. + + BASS_DSHOW_CONFIG_AudioRendererSets the audio renderer to use. + renderer (int): One of the following values: + BASS_DSHOW_DefaultAudio : pass this to select the Windows default audio renderer. + BASS_DSHOW_NULLAudio : pass this to select the NULL audio renderer. + Other values are from 1 to n. You can get audio devices using . + + BASS_DSHOW_CONFIG_FLOATDSPPass 32-bit floating-point sample data to all DSP functions? + newvalue (bool): the number of streams when using windows less mode between 1 and 15. + + + + + + + + Sets a BASS_DSHOW configuration option. + + The option to set (one of the values). + One of the values to use. + See the values to know what parameters apply to . + Options: + + BASS_DSHOW_CONFIG_VideoRendererSets the video renderer to use. + renderer (int): One of the following values: + BASS_DSHOW_VMR7 : pass this to select the VMR7 windowed renderer. + BASS_DSHOW_VMR9 : pass this to select the VMR9 windowed renderer. + BASS_DSHOW_VMR7WindowsLess : pass this to select the VMR7 window less renderer. + BASS_DSHOW_VMR9WindowsLess : pass this to select the VMR9 window less renderer. + BASS_DSHOW_EVR : pass this to select the Enhanced video renderer. + BASS_DSHOW_NULLVideo : pass this to select the NULL video renderer. + + BASS_DSHOW_CONFIG_WindowLessHandleBASS_DSHOW needs an initial window handle when using windowsless renderers, so the value parameter should be a valid window handle. + hwnd (int): a valid window handle to be used with the window less mode. + + BASS_DSHOW_CONFIG_WindowLessStreamsSets the number of streams when using windows less mode. + number (int): between 1 and 15. + + BASS_DSHOW_CONFIG_AudioRendererSets the audio renderer to use. + renderer (int): One of the following values: + BASS_DSHOW_DefaultAudio : pass this to select the Windows default audio renderer. + BASS_DSHOW_NULLAudio : pass this to select the NULL audio renderer. + Other values are from 1 to n. You can get audio devices using . + + BASS_DSHOW_CONFIG_FLOATDSPPass 32-bit floating-point sample data to all DSP functions? + newvalue (bool): the number of streams when using windows less mode between 1 and 15. + + + + + + + + Gets a BASS_DSHOW configuration option. + + The option to set (one of the values). + /// If successful, the config option value is returned (see below), else 0 is returned. Use to get the error code. + See the values to know what values might be returned. + Options: + + BASS_DSHOW_CONFIG_VideoRendererGets the video renderer in use. + BASS_DSHOW_VMR7 : the VMR7 windowed renderer. + BASS_DSHOW_VMR9 : the VMR9 windowed renderer. + BASS_DSHOW_VMR7WindowsLess : the VMR7 window less renderer. + BASS_DSHOW_VMR9WindowsLess : the VMR9 window less renderer. + BASS_DSHOW_EVR : the Enhanced video renderer. + BASS_DSHOW_NULLVideo : the NULL video renderer. + + BASS_DSHOW_CONFIG_WindowLessHandleThe window handle used. + + BASS_DSHOW_CONFIG_WindowLessStreamsThe number of streams used. + + BASS_DSHOW_CONFIG_AudioRendererGets the current audio renderer used. + + BASS_DSHOW_CONFIG_FLOATDSPIs 32-bit floating-point DSP enabled? + + + + + + + + Gets an instance IGraphBuilder interface of a channel. + + The video channel handle (as returned by ). + If successful, the new video window handle is returned, else IntPtr.Zero is returned. Use to get the error code. + + After getting an instance of the IGraphBuilder interface and add reference to it, and used it, the instance must be released by user, or memory leaks will appear. + + + + + Retrieves the current video frame. + + The video channel handle (as returned by ). + If successful, a pointer to an image (HBITMAP) is returned, else IntPtr.Zero is returned. Use to get the error code. + If the current video renderer is the NULL one, or a stream don't have video then a NULL value will be returned. + + + + Retrieves the current video frame. + + The video channel handle (as returned by ). + If successful, the current video frame image is returned, else is returned. Use to get the error code. + If the current video renderer is the NULL one, or a stream don't have video then a value will be returned. + + + + Retrieves the color controls range (min,max,step). + + The video channel handle (as returned by ). + One of the following (see ): + + BASS_DSHOW_ControlBrightnessUse this to get the brightness value ranges. + BASS_DSHOW_ControlContrastUse this to get the contrast value ranges. + BASS_DSHOW_ControlHueUse this to get the hue value ranges. + BASS_DSHOW_ControlSaturationUse this to get the saturation value ranges. + + + An instance of the structure to set the range info to. + If an error occurred then is returned, else is returned (use to get the error code). + This function was tested successfully on VMR9. It may work on other renderers and also will depend on the hardware capabilities. + + + + Retrieves the color controls range (min,max,step). + + The video channel handle (as returned by ). + One of the following (see ): + + BASS_DSHOW_ControlBrightnessUse this to get the brightness value ranges. + BASS_DSHOW_ControlContrastUse this to get the contrast value ranges. + BASS_DSHOW_ControlHueUse this to get the hue value ranges. + BASS_DSHOW_ControlSaturationUse this to get the saturation value ranges. + + + If an error occurred then is returned, else an instance of is returned (use to get the error code). + This function was tested successfully on VMR9. It may work on other renderers and also will depend on the hardware capabilities. + + + + Sets new values to color controls. + + The video channel handle (as returned by ). + Any combination of the following flags (see ): + + BASS_DSHOW_ControlBrightnessUse this to set the brightness value. + BASS_DSHOW_ControlContrastUse this to set the contrast value. + BASS_DSHOW_ControlHueUse this to set the hue value. + BASS_DSHOW_ControlSaturationUse this to set the saturation value. + + + An instance of the structure to apply the color changes from. + If an error occurred then is returned, else is returned (use to get the error code). + This function was tested successfully on VMR9. It may work on other renderers and also will depend on the hardware capabilities. + + + + Sets a video window alpha blend value. + + The video channel handle (as returned by ). + A valid window handle as returned by or 0(zero) for the main video window. + The video layer (0...15). + The new alpha blend value (0...100). + If an error occurred then is returned, else is returned (use to get the error code). + + + + Gets a video window layer alpha blend value. + + The video channel handle (as returned by ). + A valid window handle as returned by or 0(zero) for the main video window. + The video layer (0...15). + If an error occurred then -1 is returned, else the alpha blend value is returned (use to get the error code). + + + + Resizes a mixing channel + + The video channel handle (as returned by ). + The video layer (0...15). + The left position of the video. + The top position of the video. + The right position of the video. + The bottom position of the video. + If an error occurred then is returned, else is returned (use to get the error code). + + + + This method is an alternative way to get item names on methods that require callbacks. + + The type of value to get (one of the values or a valid video HSTREAM to return the name of a connected filter from that channel). + The index of the requered item (must be greater than 0). + If successful, the name of the requested item type is returned - else is returned (use to get the error code). + + + + Gets the available audio or video capture devices. + + The type of capture device to get (one of the values, either audio or video). + The user defined callback receiving the available capture devices (see ) or to retrieve only the number of available devices. + User instance data to pass to the callback function. + If successful, the number of available capture devices found is returns - else 0 is returned (use to get the error code). + + When using as a callback value this will return the number of the devices from the system only. + Another way to get the capture devices is by using the method. + + + + + Gets the available audio or video capture device profiles. + + The device you want to get then profiles from (see ). + The type of capture device to get (one of the values, either audio or video). + The user defined callback receiving the available capture devices (see ). + User instance data to pass to the callback function. + If successful, the number of available capture device profiles are returned - else 0 is returned (use to get the error code). + + + + Gets the available audio render devices available on the system. + + The user defined callback receiving the available audio render devices (see ). + User instance data to pass to the callback function. + If successful, the number of available audio render devices found is returns - else 0 is returned (use to get the error code). + + When using as a callback value this will return the number of the audio render devices from the system only. + Another way to get the capture devices is by using the method. + + + + + Overlays a HDC to the video window. + + The video channel handle (as returned by ). + An instance of the class to overlay. + If an error occurred then is returned, else is returned (use to get the error code). + + + + + + + + + + + + + Adds a new media file to a channel (e.g. for mixing multiple videos). + + The video channel handle (as returned by ). + The media file to add. + If an error occurred then is returned, else is returned (use to get the error code). + This method can be used to mix multiple videos to the same channel. + + + + Retrieves the connected filters to a channel. + + The video channel handle (as returned by ). + The user defined callback receiving the connected filters (see ). + User instance data to pass to the callback function. + If successful, the number of connected filters is returns - else 0 is returned (use to get the error code). + + When using as a callback value this will return the number of connected filters only. + Another way to get the connected filters is by using the method. + + + + + Shows a filter property page. + + The video channel handle (as returned by ). + The filter number (must be greater than 0, see ). + The parent window handle to use when showing th property page dialog. + + + + Gets the current state of a channel (playing/stopped/paused). + + The video channel handle (as returned by ). + If successful, the current is returns - else -1 is returned (use to get the error code). + + + + Sets an attribute value to a HSTREAM. + + The video channel handle (as returned by ). + One of the values. + The new attribute value. + Use to get the error code. + + + + Gets an attribute value from a HSTREAM. + + The video channel handle (as returned by ). + One of the values. + If successful, the current attribute value is returned - else 0 is returned (use to get the error code). + + + + Creates a capture stream from audio/video capture devices. + + The audio device index (use 0 to disable audio capture). + The video device index (use 0 to disable video capture). + The audio profile to use (as returned by ). + The video profile to use (as returned by ). + Any combination of these flags (see ): + + BASS_STREAM_DECODEUse this flag to enable decoding mode on a stream (e.g. to quickly extract the audio). + BASS_DSHOW_STREAM_MIXUse this flag to enable video mixing procedures on the stream. + + + If successful, the new capture handle is returned - else 0 is returned (use to get the error code). + + + + Frees a capture stream. + + The capture stream handle to free (as returned by ). + If an error occurred then is returned, else is returned (use to get the error code). + + + + Repaints a window less video renderer. + + The video channel handle (as returned by ). + A valid window handle. + A valid HDC. + If an error occurred then is returned, else is returned (use to get the error code). + + Sometimes window less video renderers needs to be repainted manually (e.g. if they cannot receive the WM_PAINT message). + + + + + + + + + + + + + Loads a BASS_DSHOW plugin. + + The plugin filename to load. + If successful, the plugin handle is returned - else 0 is returned (use to get the error code). + + + + + + + + + + + + + Loads a DirectShow plugin. + + The CLSID/GUID string of the DirectShow filter to use (e.g. use "{04FE9017-F873-410E-871E-AB91661A4EF7}" to load FFDSHOW). + The name of the filter (can be whatever you want). + If successful, the plugin handle is returned - else 0 is returned (use to get the error code). + + The necesary DirectShow codec to decode the video must be available! + + + + + + + + + + + + + Gets information about a loaded plugin. + + The plugin handled (as returned by ). + An instance of the class to store the information at. + If an error occurred then is returned, else is returned (use to get the error code). + + + + Gets information about a loaded plugin. + + The plugin handled (as returned by ). + If an error occurred then is returned, else an instance of the class is returned (use to get the error code). + + + + Removes a loaded plugin and frees all resources. + + The plugin handled to unload (as returned by ). + If an error occurred then is returned, else is returned (use to get the error code). + + + + + + + + + + + + + Creates a sample stream from a DVD or VOB file. + + The DVD or VOB filename or to render first DVD device. + An initial window handle (can be ). + Any combination of these flags : + + BASS_DSHOW_STREAM_MIXUse this flag to enable mixing video on a channel. + BASS_DSHOW_NOAUDIO_PROCUse this flag to disable audio processing. + BASS_DSHOW_STREAM_LOOPUse this flag to auto restart the stream after it's finish. + BASS_DSHOW_STREAM_VIDEOPROCUse this to enable video processor. + BASS_DSHOW_STREAM_AUTODVDUse this flag to enable auto dvd functions(on mouse down, keys etc). + BASS_STREAM_AUTOFREEAutomatically free the stream when it ends. This allows you to stream a file and forget about it, as BASS will automatically free the stream's resources when it has reached the end or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_UNICODEfile is a Unicode (16-bit characters) filename (automatically set with this overload). + + + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + The necesary codec to decode the video must be available! + + + + + Gets DVD properties. + + The DVD stream handle (as returned by ). + One of the values. + The value to get (see remarks below). + The requested property result value (use to get the error code). + See the options to know what parameters apply to . + Properties: + + BASS_DSHOW_DVDTitlesGets the number of titles from a DVD stream. + nothing: the value parameter should always be 0(zero). + + BASS_DSHOW_DVDTitleChaptersGets the number of chapters from the title. + title (int): the title ID you want to get the number of chapters from. + + BASS_DSHOW_CurentDVDTitleGets either the current title duration or position. + flag (int): use either the BASS_DSHOW_DVDCurrentTitleDuration or the BASS_DSHOW_DVDCurrentTitlePosition as the 'value' parameter. + BASS_DSHOW_DVDCurrentTitleDuration: gets the current title duration. + BASS_DSHOW_DVDCurrentTitlePosition: gets the current title position. + + + + + + + + Sets DVD properties. + + The DVD stream handle (as returned by ). + One of the values. + The new value to set (see remarks below). + If an error occurred then is returned, else is returned (use to get the error code). + See the options to know what parameters apply to . + Properties: + + BASS_DSHOW_DVD_TITLEMENUGo to DVD title menu. + nothing: the newvalue parameter should always be 0(zero). + + BASS_DSHOW_DVD_ROOTGo to DVD root. + nothing: the newvalue parameter should always be 0(zero). + + BASS_DSHOW_DVD_NEXTCHAPTERPlay next chapter. + nothing: the newvalue parameter should always be 0(zero). + + BASS_DSHOW_DVD_PREVCHAPTERPlay previous chapter. + nothing: the newvalue parameter should always be 0(zero). + + BASS_DSHOW_DVD_TITLEPlays the specified title. + title (int): the title ID to play. + + BASS_DSHOW_DVD_TITLECHAPTERPlays the specified chapter. + chapter (int): the chapter ID to play. + + BASS_DSHOW_DVDCurrentTitlePositionSets the current title playing position. + position (int): the current title playing position in seconds to set. + + + + + + + + Sets DVD MENU options. + + The DVD stream handle (as returned by ). + One of the values. + The 1st value to set (see remarks below). + The 2nd value to set (see remarks below). + If an error occurred then is returned, else is returned (use to get the error code). + See the options to know what parameters apply to and . + Menu Options: + + BASS_DSHOW_DVDSelectAtPosSelect MENU from point. + value1 parameter should be the x coordonate. + value2 parameter should be the y coordonate. + + BASS_DSHOW_DVDActionAtPosActivate Button from point. + value1 parameter should be the x coordonate. + value2 parameter should be the y coordonate. + + BASS_DSHOW_DVDActivateButtonHandle the enter key event. + value1 parameter is ignored (should be 0). + value2 parameter is ignored (should be 0). + + BASS_DSHOW_DVDSelectButtonHandle the arrow key events. + value1: 0=VK_LEFT, -1=VK_RIGHT, -2=VK_UP, -3=VK_DOWN. + value2 parameter is ignored (should be 0). + + + + + + + + + + + + + + + + + Registers you DSHOW/xVideo license. + + Your email address. + Your registration code. + If an error occurred then is returned, else is returned (use to get the error code). + + + + Send video data from a HSTREAM to a virtual webcam. + + The video channel handle (as returned by ). + Enable () or disable () the streaming of a channel. + If an error occurred then is returned, else is returned (use to get the error code). + + Make sure that xVirtualCam is registered and running when calling this function, otherwise this function will return . + + + + + Send video from user file data to a virtual webcam. + + A Handle to the application window. + The pointer to the video data to push. + If an error occurred then is returned, else is returned (use to get the error code). + + Make sure that xVirtualCam is registered and running when calling this function, otherwise this function will return . + The data parameter can't be , and MUST be 320 * 240 * 4 in size (320 Width, 240 Height, 32 bits). + + + + + Send video from user file data to a virtual webcam. + + A Handle to the application window. + The video data to push. + If an error occurred then is returned, else is returned (use to get the error code). + + Make sure that xVirtualCam is registered and running when calling this function, otherwise this function will return . + The data parameter can't be , and MUST be 320 * 240 * 4 in size (320 Width, 240 Height, 32 bits). + + + + + Send video from user file data to a virtual webcam. + + A Handle to the application window. + The video data to push. + If an error occurred then is returned, else is returned (use to get the error code). + + Make sure that xVirtualCam is registered and running when calling this function, otherwise this function will return . + The data parameter can't be , and MUST be 320 * 240 in size (320 Width, 240 Height, 32 bits). + + + + + Sets up a synchronizer on a video channel. + + The video channel handle (as e.g. returned by ). + The callback function which should be invoked with the sync. + User instance data to pass to the callback function. + If an error occurred then is returned, else is returned (use to get the error code). + + + + Sets up a user DVP function on a video stream. + + The video channel handle (as e.g. returned by ). + The callback function (see ). + User instance data to pass to the callback function. + If successfull, the new DVP handle is returned, else 0 is returned (use to get the error code). + + DVP functions can be set any time on a channel. A channel support a infinite number of DVP callbacks, and it will be processed in the same order that was added. + Use to remove a DVP. + + + + + Removes a DVP function from a video stream. + + The video channel handle (as e.g. returned by ). + Handle of the DVP function to remove from the channel (return value of a previous call). + If an error occurred then is returned, else is returned (use to get the error code). + + + + Gets the number of streams for a video handle. + + The video channel handle (as e.g. returned by ). + If successfull, the number of streams are returned, else 0 is returned (use to get the error code). + + + + + + + + + + + + + Gets information about a video stream. + + The video channel handle (as e.g. returned by ). + The zero-based stream index to retrieve the info from (use to get the number of streams). + If an error occurred then is returned, else the instance is returned (use to get the error code). + + + + Enables a stream within a video. + + The video channel handle (as e.g. returned by ). + The zero-based stream index to enable (use to get the number of streams). + If an error occurred then is returned, else is returned (use to get the error code). + + + + Enumerates connected streams on a video handle. + + The video channel handle (as e.g. returned by ). + The callback function (see ) to retrieve the stream information. + User instance data to pass to the callback function. + If successfull, the number of streams are returned, else 0 is returned (use to get the error code). + + + + Supported file extensions of the bass_dshow.dll + + + + + Supported file format name of the bass_dshow.dll + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + BASS_DSHOW error codes as returned by (int). + + + + + All is OK. + + + + + Invalid channel. + + + + + Unknown error. + + + + + Not initialized. + + + + + Position not available. + + + + + No DSHOW/xVideo. + + + + + Invalid window. + + + + + No Audio. + + + + + No Video. + + + + + Memory error. + + + + + Invalid callback. + + + + + Invalid flag(s). + + + + + Not available. + + + + + Not initialized. + + + + + Already registered. + + + + + Invalid Registration. + + + + + Initialization flags to be used with + + + + + Normal mode. + + + + + Enable multithread support. + + + + + Configuration options to be used with . + + + + + Selects the video renderer. + + + + + VMR7/VMR9 WindowLess Mode need an initial window so set a HWND to use properly VMR. + + + + + Sets the number of streams in a VMR7/9 windows less mode. + + + + + Selects audio renderer. + + + + + Enables/disables floating point processing DSP. + + + + + Configuration option flags to be used with . + + + + + Used with to select the VMR7 Windowed renderer. + + + + + Used with to select the VMR9 Windowed renderer. + + + + + Used with to select the VMR7 window less renderer. + + + + + Used with to select the VMR9 window less renderer. + + + + + Used with to select the Enhanced video renderer. + + + + + Used with to select the NULL video renderer. + + + + + Used with to select the NULL audio renderer. + + + + + Used with to select the Windows default audio device. + + + + + Capture options to be used with or . + + + + + Capture Audio. + + + + + Capture Video. + + + + + Option to be used with . + + + + + Used to get the audio capture device. + + + + + Used to get the video capture device. + + + + + Used to get the audio renderer device. + + + + + Flags to be used with and . + + + + + Gets of sets the Brightness value. + + + + + Gets of sets the Contrast value. + + + + + Gets of sets the Hue value. + + + + + Gets of sets the Saturatio value. + + + + + Channel attribute options used by and . + + + + + The audio volume level. + volume: The volume level... 0 (silent) to 1 (full). + + + + + The audio panning/balance position. + pan: The pan position... -1 (full left) to +1 (full right), 0 = centre. + + + + + The video graph rate. + + + + + The main video alpha bland value. + + + + + Channel Position Mode flags to be used with e.g. , or . + + + + + Position in seconds. + + + + + Position in frames. + + + + + Position in milliseconds. + + + + + MOD Music Flag: Stop all notes when moving position. + + + + + return values. + + + + + The channel state is unknown. + + + + + The channel is playing. + + + + + The channel is paused. + + + + + The channel is stopped. + + + + + DVD property options used by . + + + + + Gets either the current title duration or position (see BASS_DSHOW_DVDCurrentTitleDuration and BASS_DSHOW_DVDCurrentTitlePosition). + + + + + Gets the number of titles of a DVD stream. + + + + + Gets the number of chapters of a title. + + + + + Flag to be used as the 'value' parameter with the BASS_DSHOW_CurentDVDTitle option to get the current title duration. + + + + + Flag to be used as the 'value' parameter with the BASS_DSHOW_CurentDVDTitle option to get the current title position. + + + + + DVD property options used by . + + + + + Go to DVD title menu. + + + + + Go to DVD root. + + + + + Go to dvd next chapter. + + + + + Go to dvd previous chapter. + + + + + Go to dvd title. + + + + + Play chapter in current title. + + + + + Sets the current title playing position. + + + + + DVD menu options used by . + + + + + Select MENU from Point. + value1 parameter should be the x coordonate. + value2 parameter should be the y coordonate. + + + + + Activate Button from Point. + value1 parameter should be the x coordonate. + value2 parameter should be the y coordonate. + + + + + Handle a enter key down event. + value1 parameter is ignored (should be 0). + value2 parameter is ignored (should be 0). + + + + + Handle arrow key events. + value1: 0=VK_LEFT, -1=VK_RIGHT, -2=VK_UP, -3=VK_DOWN. + value2 parameter is ignored (should be 0). + + + + + Channel Sync type to be used with . + + + + + Triggered when the stream ends. + data: alwqays 0. + + + + + Triggered when a new DVD chapter starts. + data: the new chapter index. + + + + + Triggered when a title change occured in a DVD stream. + data: new title number. + + + + + Triggered when an error occured on a DVD stream. + data: alwqays 0. + + + + + Triggered by video renderers when it needs a repaint. A call to should be done, but not necessary. + data: alwqays 0. + + + + + Triggered by video renderers when the video size changed. + data: the new video width/height (the HiWord represents the new width; the LoWord represents the new height). + + + + + Channel DVP type used with a . + + + + + RGB24. Rgb24 is a sRGB format with 24 bits per pixel (BPP). Each color channel (red, green, and blue) is allocated 8 bits per pixel (BPP). + + + + + RGB32. Rgb32 is a sRGB format with 32 bits per pixel (BPP). Each color channel (red, green, and blue) is allocated 8 bits per pixel (BPP). + + + + + YUYV. + + + + + IYUV. + + + + + YVU9. + + + + + YV12. + + + + + NV12. + + + + + UYVY, + + + + + Used with to retrieve information about a video. + + + + + The video frames per seconds (0 if no video). + + + + + The height of the video in pixel (0 if no video). + + + + + The width of the video in pixel (0 if no video). + + + + + Number of audio channels (0 if no audio). + + + + + Audio sample rate (0 if no audio). + + + + + Audio resolution (8, 16, 32 bits) (0 if no audio). + + + + + Indicates if the audio is 32 bit floating point or not ( if no audio). + + + + + Default constructor. + + + + + The size of the video or the audio info (if no video). + + Returns e.g. "400x300". + + + + Used with to retrieve the color controls range. + + + + + The minimum value that a color control can have. + + + + + The maximum value that a color control can have. + + + + + The default value of the color controls (most of the time this is the value that don't affect video). + + + + + The step size between minimum and maximum values. + + + + + One of the flags. + + + + + Default constructor. + + + + + The color range info as a string. + + Returns e.g. "BASS_DSHOW_ControlBrightness: Min=-90.0, Max=90.0, Default=0.0, Step=1.0". + + + + Used with to set new values for color control. + + + + + The contrast value of the color. + + + + + The brightness value of the color. + + + + + The hue value of the color. + + + + + The saturation value of the color. + + + + + Default constructor. + + + + + The color info of the video as a string. + + Returns e.g. "Contrast=90.0, Hue=0.0, Brightness=0.0, Saturation=90.0". + + + + Only used internally! See . + + + + + plugin version. + + + + + decoder type: 1=audio, 2=video. + + + + + The pointer to the plugin description. + + + + + Used with to retrieve information on a plugin. + + This class can not be used directly! It will be returned and created by only. + + + + Plugin version. + + + + + Type of decoder: 1=audio, 2=video. + + + + + The plugin description. + + + + + Default constructor. + + + + + A description of the plugin. + + The description of the plugin structure (plgdescription). + + + + Returns if the plugin is an audio plugin. + + + + + Returns if the plugin is a video plugin. + + + + + Used with to overlay a HDC to the video window. + + + + + The overlay bitmap is visible or not? + + + + + The left position of the HDC. + + + + + The top position of the HDC. + + + + + The right position of the HDC. + + + + + The bottom position of the HDC. + + + + + The output left destination(0...1.0). + + + + + The output top destination(0...1.0). + + + + + The output right destination(0...1.0). + + + + + The output bottom destination(0...1.0). + + + + + The blend value of the overlay(0...1.0). + + + + + A RGB value that indicates wich color will not be blend over video. + + + + + A valid HDC (e.g. as retuned by 'Bitmap.GetHbitmap()'). + + Make sure to release the HDC once not needed anymore to prevent memory leaks (e.g. via gdi32.dll - DeleteObject). + + + + Default constructor. + + + + + Only used internally! See . + + + + + 0: unknown, 1: video , 2: audio , 3: subtitle + + + + + The format name. + + + + + The stream index. Use this index to enable or disable it. + + + + + Is this stream enabled? + + + + + Used with to retrieve information of a stream. + + This class can not be used directly! It will be returned and created by only. + + + + 0: unknown, 1: video , 2: audio , 3: subtitle + + + + + The format name. + + + + + The stream index. Use this index to enable or disable it. + + + + + Is this stream enabled? + + + + + Default constructor. + + + + + A description of the stream. + + The name of the stream. + + + + Returns if the stream is an audio format. + + + + + Returns if the stream is a video format. + + + + + User defined callback function to receive capture devices (see ) or audio render devices (see ). + + The name of the capture (resp. audio render) device. + The GUID of the capture (resp. audio render) device. + The user instance data given when resp. was called. + to continue, else . + + + + User defined callback function to receive capture device profiles (see ). + + The profile name of the capture device. + The user instance data given when was called. + to continue, else . + + + + User defined callback function to receive connected filters (see ). + + A pointer to the connected filter instance (IBaseFilter). Note that this instance should be used inside the callback as it is released automaticaly once the callback returned. + The name of the connected filter. + if the filter has a property page (dialog), if not. + The user instance data given when was called. + to continue, else . + + + + User defined synchronizer callback function (see for details). + + The channel that the sync applies to. + The sync occurred (one of ). + The data associated with the sync (see for details). + The user instance data given when was called. + + + + User defined DSP callback function (to be used with ). + + The DVP handle. + The video channel that the DVP applies to. + The pointer to the sample data to apply the DVP to. + The number of bytes to process. + One of the values. + The video width. + The video height. + The user instance data given when was called. + + + + User defined callback function to enumerate connected streams (see ). + + The stream format (0: unknown, 1: video , 2: audio , 3: subtitle). + The format name. + The stream index (use this index to enable or disable it). + Is this stream enabled? + The user instance data given when was called. + to continue, else . + + + + Base class for all user defined DSP classes (e.g. , or your own DSP implementations). + + This base class is not intended for direct use, but defines all abstract properties and methods which needs to be implemented by an actual DSP class. + A derived class must implement: . + The properties , , , , , , , , and + as well as the methods , and have been already implemented. + You might use this base class to derive your own DSP implementations. + In this case a derived class must implement the method and might override the method (e.g. in order to reset an internal buffer etc.). + The whole DSP framework is based on the standard BASS DSP functionality. + So as with all DSP's - the DSP is automatically freed whenever the source stream is freed, e.g. when calling or when using the flag. + + + This example shows a basic implementation of an own DSP class: + + public class DSP_MyDsp : BaseDSP + { + // First Constructor overload + public DSP_MyDsp() : base() + { + } + // Second Constructor overload + public DSP_MyDsp(int channel, int priority) : base(channel, priority, 0) + { + } + + // example implementation of the DSPCallback method + unsafe public override void DSPCallback(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + if (IsBypassed) + return; + + if (ChannelBitwidth == 16) + { + // process the data + short *data = (short*)buffer; + for (int a = 0; a < length/2; a++) + { + // your work goes here (16-bit sample data) + } + } + else if (ChannelBitwidth == 32) + { + // process the data + float *data = (float*)buffer; + for (int a = 0; a < length/4; a++) + { + // your work goes here (32-bit sample data) + } + } + else + { + // process the data + byte *data = (byte*)buffer; + for (int a = 0; a < length; a++) + { + // your work goes here (8-bit sample data) + } + } + // if you have calculated UI relevant data you might raise the event + // else comment out the following line + RaiseNotification(); + } + + public override void OnChannelChanged() + { + // override this method if you need to react on channel changes + // e.g. usefull, if an internal buffer needs to be reset etc. + } + + public override string ToString() + { + return "My DSP"; + } + } + + + + + + Default constructor. Not assigning a DSP yet. + + The DSP is not automatically assigned by this constructor! You must set the and manually prior to assigning the DSP. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + The channel does not have to be playing to set a DSP function, they can be set before and while playing. + If an instance of a derived class s being disposed, an already assigned DSP will automatically be removed from the channel. + + + + + Default constructor, which already evaluates the channel handle and assigns the DSP ( will be called automatically). + + Channel that the DSP is being applied to. + The priority of the DSP, which determines it's position in the DSP chain - DSPs with higher priority are called before those with lower. + User instance data to pass to the callback function. + The DSP is automatically assigned by this constructor! + Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + If an instance of a derived class s being disposed, an already assigned DSP will automatically be removed from the channel. + + Invalid channel used. + + + + Implement IDisposable. + + Do not make this method virtual. A derived class should not be able to override this method. + + + + Finalization code. + + This destructor will run only if the Dispose method does not get called. + It gives your base class the opportunity to finalize. Do not provide destructors in types derived from this class. + + + + Assigns the DSP to the channel (actually starts using the DSP). + + , if started successfully - else will be returned. + + Depending on which constructor you used to create an instance of the DSP, this method might have already being called. + Calling this method again, if the DSP has already being assigned will have no effect. You must call before you can call again. + Internally this method simply calls and thereby uses the , , and members. + + + + + Stops (removes) the DSP from the channel. + + , if the DSP was removed successfully - else will be returned (e.g. in case that the DSP has already been removed). + + A DSP will automatically be removed, if the channel is being freed. So there is not an explicit need of calling at the end of stream. + However, the and might return invalid handle in such case. You might use to check, if a channel is still active. + + + + + Sets the Bypass mode. + + Bypass? + If Bypass is set, a DSP function should actually return immediately and not process the sample data. + You might check the actual Bypass mode with the property. + If the DSP function should be bypassed, this needs to be implemented in the function of a derived class. + + + + + This method will be called every time the changed. + + In the default implementation this method does nothing. + It might be overridden in a derived class to reflect a channel change, e.g. to reset an internal buffer etc. + + + + This method will be called every time the method had been called. + + In the default implementation this method does nothing. + It might be overridden in a derived class to perform some addition setup calculations whenever the DSP was started, e.g. to reset an internal buffer etc. + + + + This method will be called every time the method had been called. + + In the default implementation this method does nothing. + It might be overridden in a derived class to perform some addition cleanup calculations whenever the DSP was stopped, e.g. to reset an internal buffer etc. + + + + This method will be called every time the method had been called. + + In the default implementation this method does nothing. + It might be overridden in a derived class to reflect a change of the bypass status, e.g. to reset an internal buffer etc. + + + + User defined DSP callback function which needs to be implemented in the derived class. + + The DSP handle. + Channel that the DSP is being applied to. + The buffer to apply the DSP to. The sample data is as follows: 8-bit samples are unsigned, 16-bit samples are signed, 32-bit floating-point samples range from -1 to +1 (not clipped, so can actually be outside this range). + The number of BYTES to process. + The user instance data given (see ). + A DSP function should obviously be as quick as possible... playing streams, MOD musics and other DSP functions can not be processed until it has finished. + You might use the to determine if the sample data received is 8-, 16- or 32-bit. and might be used to retrieve additional information about the channel being used. + Make sure to handle the property in order to support a bypass feature. + Some functions can cause problems if called from within a DSP (or stream) function. Do not call these functions from within a DSP callback: + , , , (or any other stream creation functions). + Also, do not call , , , , with the same channel handle as received by the callback. + + It is clever to NOT alloc buffer data (e.g. a float[]) everytime within the callback method, since ALL callbacks should be really fast! + And if you would do a 'float[] data = new float[]' every time here...the GarbageCollector would never really clean up that memory. + Sideeffects might occure, due to the fact, that BASS will call this callback too fast and too often...you might also declare the callback function as 'unsafe' and use native pointer assignements for fast processing. + However, this is not always the case, so in most examples it'll work just fine - but if you got problems - try moving any memory allocation things outside any callbacks. + + In a derived class you might call at the end of your processing, in order to fire the . + By doing so all subscribers will get notified, that the DSP processing has been done - e.g. in order to update a UI thread. + + + + + Fires the event. + + Call this method to fire the event. + This event might be used to notified the subscriber, that the DSP has processed some data and that for an example a UI needs to be updated in order to reflect this. + However, if a DSP implementation does not have any UI relevant data to show, there will be no need to call this method in your DSP implementation and can simply be omitted. + Note: This implementation ensures, that the event will be executed in the main thread the subscriber executes in! + So when subscribing to this event from UI thread, the specified event delegate will also be called in that UI thread. + + + + + Returns the name of the DSP implementation. + + Returns the name of the DSP implementation. + + + + Event handler used to notify that the DSP has processed some data. + + This event might be used to get notified, that the DSP has processed some data and that for example a UI needs to be updated in order to reflect this. + Note: This implementation ensures, that the event will be executed in the main thread the subscriber executes in! + So when subscribing to this event from UI thread, the specified event delegate will also be called in that UI thread. + In a DSP implementation you need to call in order to fire this event. + + + + + Gets or Sets the channel that the DSP is being applied to. + + If the DSP has already been assigned, changing the channel will automatically reassign the DSP to the new channel. + A DSP will automatically be removed, if the channel is being freed. + Therefore this member might return a channel handle which is not active anymore. You might use to check, if a channel is still active. + + Invalid channel used. + + + + Gets the of the assigned . + + + + + This property returns the actual bitwidth of the sample data of the channel (e.g. 8, 16, 32). + + BASS supports 8/16/32-bit sample data, so if a WAV file, for example, uses another sample resolution, it'll have to be converted by BASS. + This bitwidth represents the bitwidth which is used by BASS (e.g. in a DSP callback delegate) and does not represent the original bitwidth of the channel. + The bitwidth used by BASS is determined how the underlying channel handle was created (e.g. using with the or flag) + and if the option has been set. + If non of the above was used, by default 16 bits per sample are used. + However this bitwidth is the bitwidth in use when sending sample data to the . + If for example the or the option have been used, the DSP would receive 32-bit float samples. + + + + + This property returns the actual sample rate in Hz of the sample data BASS is using with the channel (e.g. 44100). + + + + + This property returns the actual number of channles of the sample data BASS is using with the channel (e.g. 1=mono, 2=stereo, etc.). + + BASS supports multi-channel sample data, so make sure the actual DSP implementation supports multi-channel too. + If the DSP does not support multi-channel make sure that you are using non-multi-channel handles only. + + + + + Sets or reassigns the priority of the DSP, which determines it's position in the DSP chain - DSPs with higher priority are called before those with lower. + + If the DSP has already been assigned, changing the priority will immediately reassig the DSP to the new priority. + + + + Gets or Sets the value of the user instance data to pass to the callback function (see ). + + + + + Returns the actual DSP handle (or 0, if the DSP has not been assigned to the channel). + + Caution: This member is not intended for direct use - but has more of an informal character. + A DSP will automatically be removed, if the channel is being freed. + Therefore this member might return a dsp handle which is not active anymore. You might use to check, if a channel is still active. + + + + + Returns the actual (callback delegate) which is used by the DSP. + + This callback delegate is being created when a DSP instance is being created. + Caution: This member is not intended for direct use - but has more of an informal character. + However, you might use the delegate, if you want to manually make use of the implementation of the DSP, but want to handle the entire DSP assignement yourself. + + + + + Returns if the DSP is currently bypassed (=bypass). + + Use to change the current bypass mode. + Bypassing a DSP is not done automatically! + The actual implementation of the method in a derived class must support this feature (e.g. the member has to be evaluated there). + + + + + Is the DSP assigned to an active channel? (=assigned, =not assigned). + + This property will also return , if the underlying has been freed in the meantime. + In this case the DSP will be removed automatically. + + + + Peak Level Meter DSP. + + Calculates the volume (amplitude) of the channel signal in volts or dB. + The DSP automatically converts 8-, 16- or 32-bit sample data accordingly. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + Changing the when the DSP is already assigned will automatically reassign the DSP. + Use the property to change the channel assignment at any time. If the DSP has already been assigned, the DSP will immediately be reassigned to the new channel. + The peak levels (Left channel= and Right channel=) are integer values between 0 (-inf.dB) and 32768 (0dB) - or higher, if the channel is floating-point. + Use the and properties, if you want these integer peak values already converted into dBV values (to a reference voltage of 1.0). + + + Set up a PeakLevelMeter DSP on a recording channel: + + private DSP_PeakLevelMeter _plm; + public delegate void UpdatePeakMeterCallback(); + ... + Bass.BASS_RecordInit(-1); + _recHandle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_DEFAULT, _recProc, 0); + ... + // set up a ready-made DSP (here the PeakLevelMeter) + _plm = new DSP_PeakLevelMeter(_recHandle, 1); + _plm.CalcRMS = true; + _plm.Notification += new EventHandler(UpdatePeakMeterDisplay); + ... + private void UpdatePeakMeterDisplay(object sender, EventArgs e) + { + this.progressBarRecL.Value = _plm.LevelL; + this.progressBarRecR.Value = _plm.LevelR; + this.labelRMS.Text = String.Format( "RMS: {0:#00.0} dB - AVG: {1:#00.0} dB - Peak: {2:#00.0} dB", + _plm.RMS_dBV, + _plm.AVG_dBV, + Math.Max(_plm.PeakHoldLevelL_dBV, _plm.PeakHoldLevelR_dBV) ); + } + + + + + + Creates a new instance of the PeakMeterLevel DSP, not assigning the DSP yet. + + The DSP is not automatically assigned by this constructor! You must set the and manually prior to assigning the DSP. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + The channel does not have to be playing to set a DSP function, they can be set before and while playing. + + + + + Creates a new instance of the PeakMeterLevel DSP, which already assigns the DSP ( will be called automatically). + + Channel that the DSP is being applied to. + The priority of the DSP, which determines it's position in the DSP chain - DSPs with higher priority are called before those with lower. + The DSP is automatically assigned by this constructor! + Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + + + + + Resets the and values when a channel change occurred. + + If you want to reset the peak hold values more ofen, call the method manually. + + + + Resets the and values when a channel change occurred. + + If you want to reset the peak hold values more ofen, call the method manually. + + + + User defined DSP callback function which does the peak level calculation. Not for direct use in your application! + + The DSP handle. + Channel that the DSP is being applied to. + The buffer to apply the DSP to. The sample data is as follows: 8-bit samples are unsigned, 16-bit samples are signed, 32-bit floating-point samples range from -1 to +1 (not clipped, so can actually be outside this range). + The number of BYTES to process. + The user instance data given (see ). + Not for direct use in your application! + + + + Returns the name of the DSP. + + The name of the DSP. + + + + Returns the current level signal (in linear voltage steps) of the left-channel as an integer value (between 0 and 32768, or above, if a floating-point channel was selected). + + The voltage steps are between 0 and 32768 or above. + Meaning a level signal of 1.0 volt is equivalent to a value of 32768 which means 0 dBV. A level signal of 0.0 volt is equivalent to 0 which means -Infinity dBV (-0.5 volt is approx. 16384 as an integer value or -6 dbV). + + + + + Returns the peak level signal (in linear voltage steps) of the left-channel since the last channel change or . + + + + + Returns the current level signal of the left-channel as a dBV value (between -Infinity and 0.0 - or above, if a floating-point channel was selected). + + The reference voltage for dBV is exactly 1.0 volt. + Meaning a level signal of 0.0 dbV is equivalent to 1.0 volt or a level signal of -Infinity dBV is equivalent to 0.0 volt (and -6 dBV is approx. -0.5 volt). + + + + + Returns the peak level signal of the left-channel as a dBV value (between -Infinity and 0.0 - or above, if a floating-point channel was selected) since the last channel change or . + + + + + Returns the current level signal (in linear voltage steps) of the right-channel as an integer value (between 0 and 32768, or above, if a floating-point channel was selected). + + The voltage steps are between 0 and 32768 or above. + Meaning a level signal of 1.0 volt is equivalent to a value of 32768 which means 0 dBV. A level signal of 0.0 volt is equivalent to 0 which means -Infinity dBV (-0.5 volt is approx. 16384 as an integer value or -6 dbV). + + + + + Returns the peak level signal (in linear voltage steps) of the right-channel since the last channel change or . + + + + + Returns the current level signal of the right-channel as a dBV value (between -Infinity and 0.0 - or above, if a floating-point channel was selected). + + + + + Returns the peak level signal of the right-channel as a dBV value (between -Infinity and 0.0 - or above, if a floating-point channel was selected) since the last channel change or . + + + + + Gets or Sets if the AVG and RMS values should be calculated. + + The AVG (average value) and RMS (root mean square error) might be retrieved using the and property. + If CalcRMS is turned off (, default) the and property would always return 0.0. + + + + Returns the current AVG value (average, in linear voltage steps, between 0...32768...N) of the signal. + + If CalcRMS is turned off (, default) this property would always return 0.0. + Use to turn AVG calculation on or off. + The AVG is calculated based on the samples received in each DSP call. + + + + + Returns the current AVG value (average, in dBV) of the signal. + + If CalcRMS is turned off (, default) this property would always return -Infinity. + Use to turn AVG calculation on or off. + The reference voltage for dBV is exactly 1.0 volt. + The AVG is calculated based on the samples received in each DSP call. + + + + + Returns the current RMS value (root mean square, in voltage steps, between 0...32768...N) of the signal. + + If CalcRMS is turned off (, default) this property would always return 0.0. + Use to turn RMS calculation on or off. + The RMS is calculated based on the samples received in each DSP call. + + + + + Returns the current RMS value (root mean square, in dBV) of the signal. + + If CalcRMS is turned off (, default) this property would always return -Infinity. + Use to turn RMS calculation on or off. + The reference voltage for dBV is exactly 1.0 volt. + The RMS is calculated based on the samples received in each DSP call. + + + + + Gets or Sets the update time in seconds (default is 0.1 = 100ms, max. is 60 seconds) which is the timespan being used to measure RMS and PeakLevels and is also used for Notification trigges. + + This timespan controls the following: + 1. How often the event should be raised. + 2. How many samples should be used to calculate the and values. + 3. How many samples should be used to calculate the and values. + If you set the value to 0.0 (zero) immediate update is triggered, meaning with each DSP processing step the above is being triggered/calculated. + Depending on what you want to do, good values are between 0.02 (20ms, realtime), 0.08 (80ms, user-interface) and 0.5 (500ms, RMS). + + + + + Gain DSP (amplification). + + Amplifies the channel signal by a given factor (either specified as a double factor or in dB via the property). + The DSP automatically handles 8-, 16- or 32-bit sample data accordingly. 8- and 16-bit sample data will be clipped if needed, 32-bit floating-point values will not be clipped. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + Changing the when the DSP is already assigned will automatically reassign the DSP. + Use the property to change the channel assignment at any time. If the DSP has already been assigned, the DSP will immediately be reassigned to the new channel. + The gain to be applied is defined via (factor, Min.: 0.0, Max.: 1024.0, no amplification at a value of 1.0) or (dB, Min.: -Infinity, Max.: +60, no amplification at a value of 0.0). + NOTE: This DSP does NOT support the event! + + + + + Creates a new instance of the Gain DSP, not assigning the DSP yet. + + The DSP is not automatically assigned by this constructor! You must set the and manually prior to assigning the DSP. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + The channel does not have to be playing to set a DSP function, they can be set before and while playing. + + + + + Creates a new instance of the Gain DSP, which already assigns the DSP ( will be called automatically). + + Channel that the DSP is being applied to. + The priority of the DSP, which determines it's position in the DSP chain - DSPs with higher priority are called before those with lower. + The DSP is automatically assigned by this constructor! + Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + + + + + User defined DSP callback function which does the gain amplification. Not for direct use in your application! + + The DSP handle. + Channel that the DSP is being applied to. + The buffer to apply the DSP to. The sample data is as follows: 8-bit samples are unsigned, 16-bit samples are signed, 32-bit floating-point samples range from -1 to +1 (not clipped, so can actually be outside this range). + The number of BYTES to process. + The user instance data given (see ). + Not for direct use in your application! + + + + Returns the name of the DSP. + + The name of the DSP. + + + + Gets or Sets the amplification level (factor, Min.: 0.0, Max.: 1024.0, no amplification at 1.0). + + The sample data is actually multiplied by this factory. + Values between 0.0 and less than 1.0 will actually be an attenuation of the signal level. + Values above 1.0 will actually be an amplification of the signal level, whereas a value of exactly 1.0 will leave the signal level unmodified. + The gain can also be applied via (dB, Min.: -Infinity, Max.: +60, no amplification at a value of 0.0). + + + + + Gets or Sets the amplification level (in dBV, Min.: -Infinity, Max.: +60, no amplification at a value of 0.0 dB). + + Using this property will actually convert the specified dB value into a factor (see ) internally. + The sample data is then multiplied by this factory. The reference voltage for dBV is exactly 1.0 volt. + Values between -Infinity and less than 0.0 dB will actually be an attenuation of the signal level. + Values above 0.0 dB will actually be an amplification of the signal level, whereas a value of exactly 0.0 will leave the signal level unmodified. + The gain can also be applied directly via (factor, Min.: 0.0, Max.: 1024.0, no amplification at 1.0). + + + + + Gets or Sets, if Dithering should be used (default is ). + + + Dithering adds a low level white noise to the sample data before truncating for the purpose of minimizing quantization error. + Dither only applies when processing 8- or 16-bit sample data (since here the factor might result in computation 'errors') - for 32-bit (float) sample data dither will never be applied here. + Dithering is implemented here as a triangular probability density function (TPDF), actually a " bit triangular dither" (default is 0.7). + If Dithering is disabled, the sample value will be rounded to the nearest value. + + + + + Gets or Sets the dithering bitdepth of the triangular probability density function (TPDF) - default is 0.7. + + The TPDF is implemented as a " bit triangular dither", ie. by default a "0.7 bit triangular dither" is used. + Dithering only applies here when processing 8- or 16-bit sample data and when the property has been set to . + + + + + Stereo Panning DSP (balance). + + A stereo Panning DSP. Panning is controlled via the property. + Note: This DSP only works on streams with a multiple of 2 channels (e.g. stereo, quadro, etc.). + The DSP automatically handles 8-, 16- or 32-bit sample data accordingly. 8- and 16-bit sample data will be clipped if needed, 32-bit floating-point values will not be clipped. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + Changing the when the DSP is already assigned will automatically reassign the DSP. + Use the property to change the channel assignment at any time. If the DSP has already been assigned, the DSP will immediately be reassigned to the new channel. + NOTE: This DSP does NOT support the event! + + + + + Creates a new instance of the Panning DSP, not assigning the DSP yet. + + The DSP is not automatically assigned by this constructor! You must set the and manually prior to assigning the DSP. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + The channel does not have to be playing to set a DSP function, they can be set before and while playing. + + + + + Creates a new instance of the Panning DSP, which already assigns the DSP ( will be called automatically). + + Channel that the DSP is being applied to. + The priority of the DSP, which determines it's position in the DSP chain - DSPs with higher priority are called before those with lower. + The DSP is automatically assigned by this constructor! + Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + + + + + User defined DSP callback function which does the panning. Not for direct use in your application! + + The DSP handle. + Channel that the DSP is being applied to. + The buffer to apply the DSP to. The sample data is as follows: 8-bit samples are unsigned, 16-bit samples are signed, 32-bit floating-point samples range from -1 to +1 (not clipped, so can actually be outside this range). + The number of BYTES to process. + The user instance data given (see ). + Not for direct use in your application! + + + + Returns the name of the DSP. + + The name of the DSP. + + + + Defines the panning factor between -1.0 (pan left) and 1.0 (pan right), center is at 0.0 (default). + + Assigning values outside the valid range [-1..1] will be capped automatically. + + + + Gets or Sets, if Dithering should be used (default is ). + + + Dithering adds a low level white noise to the sample data before truncating for the purpose of minimizing quantization error. + Dither only applies when processing 8- or 16-bit sample data (since here the factor might result in computation 'errors') - for 32-bit (float) sample data dither will never be applied here. + Dithering is implemented here as a triangular probability density function (TPDF), actually a " bit triangular dither" (default is 0.7). + If Dithering is disabled, the sample value will be rounded to the nearest value. + + + + + Gets or Sets the dithering bitdepth of the triangular probability density function (TPDF) - default is 0.7. + + The TPDF is implemented as a " bit triangular dither", ie. by default a "0.7 bit triangular dither" is used. + Dithering only applies here when processing 8- or 16-bit sample data and when the property has been set to . + + + + + Mono DSP (converts a stereo signal to a mono signal). + + A stereo to mono DSP. + Note: This DSP only works on streams with a multiple of 2 channels (e.g. stereo, quadro, etc.). + The DSP automatically handles 8-, 16- or 32-bit sample data accordingly. 8- and 16-bit sample data will be clipped if needed, 32-bit floating-point values will not be clipped. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + Changing the when the DSP is already assigned will automatically reassign the DSP. + Use the property to change the channel assignment at any time. If the DSP has already been assigned, the DSP will immediately be reassigned to the new channel. + NOTE: This DSP does NOT support the event! + + + + + Creates a new instance of the Mono DSP, not assigning the DSP yet. + + The DSP is not automatically assigned by this constructor! You must set the and manually prior to assigning the DSP. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + The channel does not have to be playing to set a DSP function, they can be set before and while playing. + + + + + Creates a new instance of the Mono DSP, which already assigns the DSP ( will be called automatically). + + Channel that the DSP is being applied to. + The priority of the DSP, which determines it's position in the DSP chain - DSPs with higher priority are called before those with lower. + The DSP is automatically assigned by this constructor! + Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + + + + + User defined DSP callback function which does the mono conversion. Not for direct use in your application! + + The DSP handle. + Channel that the DSP is being applied to. + The buffer to apply the DSP to. The sample data is as follows: 8-bit samples are unsigned, 16-bit samples are signed, 32-bit floating-point samples range from -1 to +1 (not clipped, so can actually be outside this range). + The number of BYTES to process. + The user instance data given (see ). + Not for direct use in your application! + + + + Returns the name of the DSP. + + The name of the DSP. + + + + Gets or Sets, if the stereo signal should be inverted (forces inverted stereo information to be removed - default is ). + + Forcing to remove any stereo information which often results in a kind of karaoce effect. Also might be used, if there is an inverted phase in the stereo signal, if a mono signal had been recorded in stereo. + + + + Gets or Sets, if Dithering should be used (default is ). + + + Dithering adds a low level white noise to the sample data before truncating for the purpose of minimizing quantization error. + Dither only applies when processing 8- or 16-bit sample data (since here the mono calculation might result in computation 'errors') - for 32-bit (float) sample data dither will never be applied here. + Dithering is implemented here as a triangular probability density function (TPDF), actually a " bit triangular dither" (default is 0.7). + If Dithering is disabled, the sample value will be rounded to the nearest value. + + + + + Gets or Sets the dithering bitdepth of the triangular probability density function (TPDF) - default is 0.7. + + The TPDF is implemented as a " bit triangular dither", ie. by default a "0.7 bit triangular dither" is used. + Dithering only applies here when processing 8- or 16-bit sample data and when the property has been set to . + + + + + Stereo Enhancer DSP (actually also removes mono signals). + + A simple stereo enhancer. Use the property to contol the wideness of the stereo effect and the property to control how much the effect should impact the original signal. + The DSP automatically handles 8-, 16- or 32-bit sample data accordingly. 8- and 16-bit sample data will be clipped if needed, 32-bit floating-point values will not be clipped. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + Changing the when the DSP is already assigned will automatically reassign the DSP. + Use the property to change the channel assignment at any time. If the DSP has already been assigned, the DSP will immediately be reassigned to the new channel. + NOTE: This DSP does NOT support the event! + + + + + Creates a new instance of the Stereo Enhancer DSP, not assigning the DSP yet. + + The DSP is not automatically assigned by this constructor! You must set the and manually prior to assigning the DSP. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + The channel does not have to be playing to set a DSP function, they can be set before and while playing. + + + + + Creates a new instance of the Stereo Enhancer DSP, which already assigns the DSP ( will be called automatically). + + Channel that the DSP is being applied to. + The priority of the DSP, which determines it's position in the DSP chain - DSPs with higher priority are called before those with lower. + The DSP is automatically assigned by this constructor! + Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + + + + + User defined DSP callback function which does the stereo enhancement. Not for direct use in your application! + + The DSP handle. + Channel that the DSP is being applied to. + The buffer to apply the DSP to. The sample data is as follows: 8-bit samples are unsigned, 16-bit samples are signed, 32-bit floating-point samples range from -1 to +1 (not clipped, so can actually be outside this range). + The number of BYTES to process. + The user instance data given (see ). + Not for direct use in your application! + + + + Returns the name of the DSP. + + The name of the DSP. + + + + Gets or Sets the stereo wide (coefficient) controling the stereo enhancement between 0.0 (narrow, mono signal) and 10.0 (wide, enhanced stereo signal) - default is 2.0. + + A values of 0.0 will result in a narrow mono signal and a value of 1.0 in a original stereo, whereas values above 1.0 will provide an enhanced wide stereo signal. + + + + + Gets or Sets the Wet/Dry ratio between 0.0 (dry, unprocessed signal only) and 1.0 (wet, processed signal only) - default is 0.5. + + This property defines how much of the effect signal will be mixed into the original signal. + A values of 0.0 means, that only the dry (unprocessed, original) signal is used. A value of 1.0 means, that only the wet (processed) signal is used. + If you assign values outside this range they will actually be capped to [0.0...1.0]. + + + + + Gets or Sets, if Dithering should be used (default is ). + + + Dithering adds a low level white noise to the sample data before truncating for the purpose of minimizing quantization error. + Dither only applies when processing 8- or 16-bit sample data (since here the effect calculation might result in computation 'errors') - for 32-bit (float) sample data dither will never be applied here. + Dithering is implemented here as a triangular probability density function (TPDF), actually a " bit triangular dither" (default is 0.7). + If Dithering is disabled, the sample value will be rounded to the nearest value. + + + + + Gets or Sets the dithering bitdepth of the triangular probability density function (TPDF) - default is 0.7. + + The TPDF is implemented as a " bit triangular dither", ie. by default a "0.7 bit triangular dither" is used. + Dithering only applies here when processing 8- or 16-bit sample data and when the property has been set to . + + + + + IIR Delay Filter DSP. + + An IIR Delay filer (flexible-time, non-sample quantized delay). Use the resp. the property to control the delay time. The and properties conrol the ratio between the original signal and the processed effect signal as well as the ratio of the processed delay which will be mixed into the delay buffer. + The DSP automatically handles 8-, 16- or 32-bit sample data accordingly. 8- and 16-bit sample data will be clipped if needed, 32-bit floating-point values will not be clipped. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + Changing the when the DSP is already assigned will automatically reassign the DSP. + Use the property to change the channel assignment at any time. If the DSP has already been assigned, the DSP will immediately be reassigned to the new channel. + NOTE: This DSP does NOT support the event! + + + + + Creates a new instance of the IIR Delay Filter DSP, not assigning the DSP yet. + + The maximum delay buffer size in seconds. + The DSP is not automatically assigned by this constructor! You must set the and manually prior to assigning the DSP. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + The channel does not have to be playing to set a DSP function, they can be set before and while playing. + + + + + Creates a new instance of the IIR Delay Filter DSP, which already assigns the DSP ( will be called automatically). + + Channel that the DSP is being applied to. + The priority of the DSP, which determines it's position in the DSP chain - DSPs with higher priority are called before those with lower. + The maximum delay buffer size in seconds (between 0.001 and 60.0). + The DSP is automatically assigned by this constructor! + Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Clears the internal buffer. + + It is a good idea to call this method whenever you change the position of the stream. + This will also automatically be called . + + + + + This method will be called every time the changed. + + It resets the internal buffer. + + + + User defined DSP callback function which adds the delay effect. Not for direct use in your application! + + The DSP handle. + Channel that the DSP is being applied to. + The buffer to apply the DSP to. The sample data is as follows: 8-bit samples are unsigned, 16-bit samples are signed, 32-bit floating-point samples range from -1 to +1 (not clipped, so can actually be outside this range). + The number of BYTES to process. + The user instance data given (see ). + Not for direct use in your application! + + + + Returns the name of the DSP. + + The name of the DSP. + + + + Gets or Sets the Wet/Dry ratio between 0.0 (dry, unprocessed signal only) and 1.0 (wet, processed signal only) - default is 0.5. + + This property defines how much of the effect signal will be mixed into the original signal. + A values of 0.0 means, that only the dry (unprocessed, original) signal is used. A value of 1.0 means, that only the wet (processed) signal is used. + If you assign values outside this range they will actually be capped to [0.0...1.0]. + + + + + Gets or Sets the feedback factor of the processed signal between 0.0 (none) and 1.0 (full) which should be stored in the delay buffer - default is 0.5. + + This property defines how much of the processed signal will be feed back to the delay buffer. + A values of 0.0 means, that only the original signal is used and stored in the delay buffer. + A value of 1.0 means, that only the processed signal is used and stored in the delay buffer. + If you assign values outside this range they will actually be capped to [0.0...1.0]. + + + + + Gets or Sets the Delay in number of samples (default is 4096). + + + + + Gets or Sets the Delay in seconds (e.g. 0.01 for 10ms - between 0.0 and 60.0). + + + + + Gets or Sets, if Dithering should be used (default is ). + + + Dithering adds a low level white noise to the sample data before truncating for the purpose of minimizing quantization error. + Dither only applies when processing 8- or 16-bit sample data (since here the effect calculation might result in computation 'errors') - for 32-bit (float) sample data dither will never be applied here. + Dithering is implemented here as a triangular probability density function (TPDF), actually a " bit triangular dither" (default is 0.7). + If Dithering is disabled, the sample value will be rounded to the nearest value. + + + + + Gets or Sets the dithering bitdepth of the triangular probability density function (TPDF) - default is 0.7. + + The TPDF is implemented as a " bit triangular dither", ie. by default a "0.7 bit triangular dither" is used. + Dithering only applies here when processing 8- or 16-bit sample data and when the property has been set to . + + + + + Soft Saturation DSP (a waveshaper). + + A Soft Saturation DSP doing some wave sharping. Use the property to play around with sharping effect. + Basically it reduces/modifies the level signal, if above the value. If the signal is below the the signal will be left unchanged. + The effect is a good combination with a gain effect to minimize distortion or clipping which might happen with loud signal peaks. + The DSP automatically handles 8-, 16- or 32-bit sample data accordingly. 8- and 16-bit sample data will be clipped if needed, 32-bit floating-point values will not be clipped. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + Changing the when the DSP is already assigned will automatically reassign the DSP. + Use the property to change the channel assignment at any time. If the DSP has already been assigned, the DSP will immediately be reassigned to the new channel. + NOTE: This DSP does NOT support the event! + + + + + Creates a new instance of the Soft Saturation DSP, not assigning the DSP yet. + + The DSP is not automatically assigned by this constructor! You must set the and manually prior to assigning the DSP. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + The channel does not have to be playing to set a DSP function, they can be set before and while playing. + + + + + Creates a new instance of the Soft Saturation DSP, which already assigns the DSP ( will be called automatically). + + Channel that the DSP is being applied to. + The priority of the DSP, which determines it's position in the DSP chain - DSPs with higher priority are called before those with lower. + The DSP is automatically assigned by this constructor! + Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + + + + + User defined DSP callback function which does the soft saturation wave sharping. Not for direct use in your application! + + The DSP handle. + Channel that the DSP is being applied to. + The buffer to apply the DSP to. The sample data is as follows: 8-bit samples are unsigned, 16-bit samples are signed, 32-bit floating-point samples range from -1 to +1 (not clipped, so can actually be outside this range). + The number of BYTES to process. + The user instance data given (see ). + Not for direct use in your application! + + + + Returns the name of the DSP. + + The name of the DSP. + + + + Gets or Sets the Depth between 0.0 and 1.0 (default is 0.5, 0.0=off). + + The signal will be warmed when set above 0.0. + + + + Gets or Sets the Soft Saturation factor between 0.0 and 0.99998848714 (default is 0.5). + + The signal will be dynamically sharped, if the signal amplitude is above this given factor. + + + + Gets or Sets the Soft Saturation factor in dBV between NegativeInfinity and -0.0001 (default is -6 dB). + + The signal will be dynamically sharped, if the signal amplitude is above this given factor. + + + + Gets or Sets, if Dithering should be used (default is ). + + + Dithering adds a low level white noise to the sample data before truncating for the purpose of minimizing quantization error. + Dither only applies when processing 8- or 16-bit sample data (since here the mono calculation might result in computation 'errors') - for 32-bit (float) sample data dither will never be applied here. + Dithering is implemented here as a triangular probability density function (TPDF), actually a " bit triangular dither" (default is 0.7). + If Dithering is disabled, the sample value will be rounded to the nearest value. + + + + + Gets or Sets the dithering bitdepth of the triangular probability density function (TPDF) - default is 0.7. + + The TPDF is implemented as a " bit triangular dither", ie. by default a "0.7 bit triangular dither" is used. + Dithering only applies here when processing 8- or 16-bit sample data and when the property has been set to . + + + + + Stream Copy DSP (to clone any BASS stream). + + A Stream Copy DSP actually provides a synchronized clone of the which can for example be used to playout the to another device or spreakers. + Use the property to specify the BASS device which should be used for the stream copy. + Use the property to specify additional flags which should be used create the stream copy. + The and the handles will be linked. + So the channel will be started/stopped/paused/resumed together with the original . + When using with a mixer stream (see ) you need to set the and properties accordingly. + It is possible to copy either a mixer source stream or the mixer stream itself (in both cases the handle must be set - so the might be equal to the ). + If you specify a the handle will automatically be add as a new source channel to that mixer (in such case make sure to use BASS_STREAM_DECODE as a ). + The property will define, if the final output is a buffered stream or not (so if using with a you might still need to set this to ). + + The DSP automatically handles 8-, 16- or 32-bit sample data accordingly. 8- and 16-bit sample data will be clipped if needed, 32-bit floating-point values will not be clipped. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + Changing the when the DSP is already assigned will automatically reassign the DSP. + Use the property to change the original channel assignment at any time. If the DSP has already been assigned, the DSP will immediately be reassigned to the new channel. + NOTE: This DSP does NOT support the event! + Internally the implementation uses to keep the sample data of the original stream in sync with the custom created push stream (the 'StreamCopy' is created via + and linked to the source stream via ). + It is not recommended to use this DSP with ASIO sources (use the DSP instead). + So when you now call the method on the DSP_StreamCopy instance the copied-stream will be freed (but not the source stream). + The same is true, if the GarbageCollector disposes your DSP_StreamCopy instance, since within the dispose implementation the method will be called. + However, stopping the source stream will not reset the copied-stream! Also the copied-stream will not be freed automatically, if you simply free the original stream (only the DSP will be removed from it). + So when you free your source stream (or the playback ends) it is advised to call the method on your DSP_StreamCopy method as well. So that the DSP is removed and the copied-stream will be removed/freed! + When you need to start the original stream again, simply call again. + Here is a full overview of all possible scenarios: + A) Stopping/Releasing the source stream: + -> call to also free the (and internal DSP). + A.1) Restarting the same source stream: + -> call if you need to start the source stream again. + A.2) Assigning a new source stream: + -> set the to the new source stream (see B). + B) Changing the of the DSP_StreamCopy instance: + -> the current (if existing) will be freed automatically (and internal DSP). + A new is created automatically for the new source stream. + C) Changing the of the DSP_StreamCopy instance: + -> the current (if existing) will be freed automatically. + A new is created automatically on the new device. + D) Disposing of the DSP_StreamCopy instance (e.g. via GC): + -> the current (if existing) will be freed automatically (and internal DSP). + + + Create a copy of a regular BASS stream and play it on another BASS device: + + private DSP_StreamCopy _streamCopy; + ... + Bass.BASS_Init(2, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero); + Bass.BASS_Init(1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero); + ... + // create the original stream (on device 1) + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_SAMPLE_FLOAT); + // start playing it... + Bass.BASS_ChannelPlay(stream, false); + ... + _streamCopy = new DSP_StreamCopy(); + BASS_INFO info = Bass.BASS_GetInfo(); + _streamCopy.OutputLatency = info.latency; + // the stream to copy + _streamCopy.ChannelHandle = stream; + _streamCopy.DSPPriority = -1000; + // use device 2 to create the copy on + _streamCopy.StreamCopyDevice = 2; + // use the exact same stream flags for the stream copy + _streamCopy.StreamCopyFlags = _streamCopy.ChannelInfo.flags; + _streamCopy.Start(); + + + Private _streamCopy As DSP_StreamCopy + ... + Bass.BASS_Init(2, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) + Bass.BASS_Init(1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) + ... + ' create the original stream (on device 1) + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_SAMPLE_FLOAT) + ' start playing it... + Bass.BASS_ChannelPlay(stream, False) + ... + _streamCopy = New DSP_StreamCopy() + BASS_INFO info = Bass.BASS_GetInfo() + _streamCopy.OutputLatency = info.latency + ' the stream to copy + _streamCopy.ChannelHandle = stream + _streamCopy.DSPPriority = -1000 + ' use device 2 to create the copy on + _streamCopy.StreamCopyDevice = 2 + ' use the exact same stream flags for the stream copy + _streamCopy.StreamCopyFlags = _streamCopy.ChannelInfo.flags + _streamCopy.Start() + + Create a copy of a regular BASS stream and play it on other speakers: + + private DSP_StreamCopy _streamCopy; + ... + Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_SPEAKERS, IntPtr.Zero); + ... + // create the original stream (using front speakers) + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, + BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_SPEAKER_FRONT); + // start playing it... + Bass.BASS_ChannelPlay(stream, false); + ... + _streamCopy = new DSP_StreamCopy(); + BASS_INFO info = Bass.BASS_GetInfo(); + _streamCopy.OutputLatency = info.latency; + // the stream to copy + _streamCopy.ChannelHandle = stream; + _streamCopy.DSPPriority = -1000; + // use different speaker flags for the stream copy + _streamCopy.StreamCopyFlags = BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_SPEAKER_REAR; + _streamCopy.Start(); + + + Private _streamCopy As DSP_StreamCopy + ... + Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_SPEAKERS, IntPtr.Zero) + ... + ' create the original stream (using front speakers) + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, + BASSFlag.BASS_SAMPLE_FLOAT Or BASSFlag.BASS_SPEAKER_FRONT) + ' start playing it... + Bass.BASS_ChannelPlay(stream, False) + ... + _streamCopy = New DSP_StreamCopy() + BASS_INFO info = Bass.BASS_GetInfo(); + _streamCopy.OutputLatency = info.latency; + ' the stream to copy + _streamCopy.ChannelHandle = stream + _streamCopy.DSPPriority = -1000 + ' use different speaker flags for the stream copy + _streamCopy.StreamCopyFlags = BASSFlag.BASS_SAMPLE_FLOAT Or BASSFlag.BASS_SPEAKER_REAR + _streamCopy.Start() + + Create a copy of a BASSmix source mixer stream and copy it to another BASSmix mixer as a source: + + private DSP_StreamCopy _streamCopy; + ... + _streamCopy = new DSP_StreamCopy(); + BASS_INFO info = Bass.BASS_GetInfo(); + _streamCopy.OutputLatency = info.latency; + _streamCopy.DSPPriority = -9000; + ... + // assign the copy + _streamCopy.ChannelHandle = _mixerSourceStream; // the stream to copy + _streamCopy.StreamCopyDevice = 0; + _streamCopy.StreamCopyFlags = BASSFlag.BASS_STREAM_DECODE; + _streamCopy.SourceMixerStream = MixerStreamA; + _streamCopy.TargetMixerStream = MixerStreamB; + _streamCopy.IsOutputBuffered = true; + _streamCopy.Start(); + ... + // start playing the original source + BassMix.BASS_Mixer_ChannelPlay(_mixerSourceStream); + if (_streamCopy.IsAssigned) + _streamCopy.ReSync(); + ... + // pausing the original source + BassMix.BASS_Mixer_ChannelPause(_mixerSourceStream); + ... + + + Private _streamCopy As DSP_StreamCopy + ... + _streamCopy = New DSP_StreamCopy() + BASS_INFO info = Bass.BASS_GetInfo(); + _streamCopy.OutputLatency = info.latency; + _streamCopy.DSPPriority = -9000 + ... + ' assign the copy + _streamCopy.ChannelHandle = _mixerSourceStream ' the stream to copy + _streamCopy.StreamCopyDevice = 0 + _streamCopy.StreamCopyFlags = BASSFlag.BASS_STREAM_DECODE + _streamCopy.SourceMixerStream = MixerStreamA + _streamCopy.TargetMixerStream = MixerStreamB + _streamCopy.IsOutputBuffered = true + _streamCopy.Start() + ... + ' start playing the original source + BassMix.BASS_Mixer_ChannelPlay(_mixerSourceStream) + If _streamCopy.IsAssigned Then + _streamCopy.ReSync(); + End If + ... + ' pausing the original source + BassMix.BASS_Mixer_ChannelPause(_mixerSourceStream) + ... + + + + + + Creates a new instance of the Stream Copy DSP, not assigning the DSP yet. + + The DSP is not automatically assigned by this constructor! You must set the and manually prior to assigning the DSP. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + The channel does not have to be playing to set a DSP function, they can be set before and while playing. + + + + + Creates a new instance of the Stream Copy DSP, which already assigns the DSP ( will be called automatically). + + Channel that the DSP is being applied to. + The priority of the DSP, which determines it's position in the DSP chain - DSPs with higher priority are called before those with lower. + The DSP is automatically assigned by this constructor! + Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + + + + + Re-Synchronizes the with the when using BASSmix mixer channels. + + + Call this method right after you unpaused or start playing the , and if you are using this instance with a in order to resync the stream copy after it was paused. + + + + + Occures when the has been changed. + + NOT for direct use in your application! + + + + Occures when the method was called. + + NOT for direct use in your application! + + + + Occures when the method was called. + Actually creates the custom push stream here. + + NOT for direct use in your application! + + + + Occures when the method was called. + Actually frees the custom stream here. + + NOT for direct use in your application! + + + + User defined DSP callback function which does the stream copy operation. Not for direct use in your application! + + The DSP handle. + Channel that the DSP is being applied to. + The buffer to apply the DSP to. The sample data is as follows: 8-bit samples are unsigned, 16-bit samples are signed, 32-bit floating-point samples range from -1 to +1 (not clipped, so can actually be outside this range). + The number of BYTES to process. + The user instance data given (see ). + Not for direct use in your application! + + + + Returns the name of the DSP. + + The name of the DSP. + + + + Gets the copied BASS stream (the created custom push stream). + + Note: The and the handles will be linked. + So the channel will be started/stopped/paused/resumed together with the original . + Use the property to specify the BASS device which should be used for the stream copy. Use the property to specify additional flags which should be used create the stream copy. + + + + + Gets or Sets the flags which should be used to create the . + + Note: Setting the stream copy flags while the DSP_StreamCopy is already assigned will automatically (re)start it. + By default no flags are used with the stream copy, so make sure to set these flags accordingly to your scenario. + E.g. add a BASS_STREAM_DECODE flag, if you want to create a decoding copy which you might add to a mixer stream. + + + + + Gets or Sets the BASS device, which should be used for the stream copy. + + Note: Setting the BASS device while the DSP_StreamCopy is already assigned will automatically (re)start it. + By default the current device is being used. + Make also sure, that the BASS device has been initializes (see ) before. + + + + + Gets or Sets the output latency in milliseconds (default = 0). + + The output latency compensates for an additional delay of the DirectSound buffer. + You should initialize this property with the BASS_INFO.latency member when using with a buffered output. + + + + Gets or Sets, if the should be buffered or not (default is ). + + If set to , the will be (pre)buffered with the data available from the . + This option is useful, if you want to use this instance with a buffered output stream. + If set to the will not be (pre)buffered, which is usefull when used with unbuffered outputs (e.g. ASIO). + Note: Setting this member while the DSP_StreamCopy is already assigned will automatically (re)start it. + + + + + Gets or Sets the mixer handle of the mixer from which you are cloning (see BASSmix addon). + + + It is possible to copy either a mixer's source stream or the mixer stream itself. + In both cases you must specify the mixers channel handle - so if you clone the mixer itself the will be equal to this property. + If you specify a the handle will automatically be add as a new source channel to that mixer (in such case make sure to use BASS_STREAM_DECODE as a ). + The property will define, if the final output is a buffered stream or not (so if using with a you might still need to set it to ). + + + + + Gets or Sets the mixer handle of the mixer to which the handle should be added (see BASSmix addon). + + + If you specify a the handle will automatically be add as a new source channel to that mixer + (the BASS_STREAM_DECODE flag will automatically be added to the ). + The property will define, if the final output is a buffered stream or not (so if using with a you might still need to set it to ). + + + + + Stream Buffer DSP (to clone a BASS stream's current sample data to a decoding stream). + + A Stream Buffer DSP actually provides a synchronized clone of the 's sample data in a new decoding channel which can for example be used to get FFT or level data. + Use the decoding channel with the or methods to do retrieve the cloned sample data. + This DSP will always provide a decoding channel (). + The DSP automatically handles 8-, 16- or 32-bit sample data accordingly. 8- and 16-bit sample data will be clipped if needed, 32-bit floating-point values will not be clipped. + Note: The channel flags of the being used are actually the same as from the original , but if you have FLOATDSP enabled the FLOAT flag will be added automatically. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + Changing the when the DSP is already assigned will automatically reassign the DSP. + Use the property to change the channel assignment at any time. If the DSP has already been assigned, the DSP will immediately be reassigned to the new channel. + Use the property (which represents a custom decoding stream) to get the level or FFT data from it. + If the is attached to a buffered output stream (e.g. via BASSmix to a mixer stream) there will be a delay due to the additional output buffer. + Use the property in order to compensate for that (or leave to it's default 0 value in order to simply use a non-synchronized direct buffer - in such case the internal buffer will return the data as being heard). + In addition you might use the property to specify, if the created will be used with a buffered output stream. + In such case the decoding position will be aligned to the output buffer (default is ). + By default the internal buffer size is determined from the current BASS_CONFIG_BUFFER setting. + However, that might not always be correct, since the buffer size must also be equal to the one used with the . + So you might change that using the property. + NOTE: This DSP does NOT support the event! + + + Create an exact shadow copy of a decoding stream: + + private DSP_BufferStream _bufferStream; + ... + // create a mixer outout stream + _mixer1 = BassMix.BASS_MIXER_StreamCreate(44100, 2, BASSFlag.BASS_DEFAULT); + Bass.BASS_ChannelPlay(_mixer1, false); + _mixer2 = BassMix.BASS_MIXER_StreamCreate(44100, 2, BASSFlag.BASS_DEFAULT); + Bass.BASS_ChannelPlay(_mixer2, false); + // create a source stream and add it to the mixer1 + _stream = Bass.BASS_StreamCreateFile(_fileName, 0, 0, BASSFlag.BASS_SAMPLE_FLOAT | + BASSFlag.BASS_STREAM_DECODE); + BassMix.BASS_Mixer_StreamAddChannel(_mixer1, _stream, BASSFlag.BASS_DEFAULT); + ... + // create a clone of the source stream to add it to mixer2 + _bufferStream = new DSP_BufferStream(); + _bufferStream.ChannelHandle = _stream; // the stream to copy + _bufferStream.DSPPriority = -4000; + _bufferStream.Start(); + BassMix.BASS_Mixer_StreamAddChannel(_mixer1, _bufferStream.BufferStream, BASSFlag.BASS_DEFAULT); + + + Private _bufferStream As DSP_BufferStream + ... + ' create a mixer outout stream + _mixer1 = BassMix.BASS_MIXER_StreamCreate(44100, 2, BASSFlag.BASS_DEFAULT) + Bass.BASS_ChannelPlay(_mixer1, False) + _mixer2 = BassMix.BASS_MIXER_StreamCreate(44100, 2, BASSFlag.BASS_DEFAULT) + Bass.BASS_ChannelPlay(_mixer2, False) + ' create a source stream and add it to the mixer1 + _stream = Bass.BASS_StreamCreateFile(_fileName, 0, 0, BASSFlag.BASS_SAMPLE_FLOAT Or + BASSFlag.BASS_STREAM_DECODE) + BassMix.BASS_Mixer_StreamAddChannel(_mixer1, _stream, BASSFlag.BASS_DEFAULT) + ... + ' create a clone of the source stream to add it to mixer2 + _bufferStream = New DSP_BufferStream() + _bufferStream.ChannelHandle = _stream ' the stream to copy + _bufferStream.DSPPriority = - 4000 + _bufferStream.Start() + BassMix.BASS_Mixer_StreamAddChannel(_mixer1, _bufferStream.BufferStream, BASSFlag.BASS_DEFAULT) + + Create a buffered stream copy to sync a FFT or GetLevel call: + + private DSP_BufferStream _bufferStream; + ... + // create a mixer outout stream + _mixer = BassMix.BASS_MIXER_StreamCreate(44100, 2, BASSFlag.BASS_DEFAULT); + Bass.BASS_ChannelPlay(BASSFlag.BASS_DEFAULT, false); + // create a source stream and add it to the mixer + _stream = Bass.BASS_StreamCreateFile(_fileName, 0, 0, BASSFlag.BASS_SAMPLE_FLOAT | + BASSFlag.BASS_STREAM_DECODE); + BassMix.BASS_Mixer_StreamAddChannel(_mixer, _stream, BASSFlag.BASS_DEFAULT); + ... + // create a buffer of the source stream for level and/or FFT data retrival in sync with the mixer output + _bufferStream = new DSP_BufferStream(); + _bufferStream.ChannelHandle = _stream; // the stream to copy + _bufferStream.OutputHandle = _mixer; // the stream to sync with (what's being heard) + _bufferStream.DSPPriority = -4000; + _bufferStream.Start(); + ... + float[] fft = new float[2048]; + Bass.BASS_ChannelGetData(_bufferStream.BufferStream, fft, (int)BASSData.BASS_DATA_FFT4096); + + + Private _bufferStream As DSP_BufferStream + ... + ' create a mixer outout stream + _mixer = BassMix.BASS_MIXER_StreamCreate(44100, 2, BASSFlag.BASS_DEFAULT) + Bass.BASS_ChannelPlay(BASSFlag.BASS_DEFAULT, False) + ' create a source stream and add it to the mixer + _stream = Bass.BASS_StreamCreateFile(_fileName, 0, 0, BASSFlag.BASS_SAMPLE_FLOAT Or + BASSFlag.BASS_STREAM_DECODE) + BassMix.BASS_Mixer_StreamAddChannel(_mixer, _stream, BASSFlag.BASS_DEFAULT) + ... + ' create a buffer of the source stream for level and/or FFT data retrival in sync with the mixer output + _bufferStream = New DSP_BufferStream() + _bufferStream.ChannelHandle = _stream ' the stream to copy + _bufferStream.OutputHandle = _mixer ' the stream to sync with (what's being heard) + _bufferStream.DSPPriority = - 4000 + _bufferStream.Start() + ... + Dim fft(2048) As Single + Bass.BASS_ChannelGetData(_bufferStream.BufferStream, fft, CInt(BASSData.BASS_DATA_FFT4096)) + + + + + + Creates a new instance of the Stream Buffer DSP, not assigning the DSP yet. + + The DSP is not automatically assigned by this constructor! You must set the and manually prior to assigning the DSP. + Use to assign the DSP to the channel. Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + The channel does not have to be playing to set a DSP function, they can be set before and while playing. + + + + + Creates a new instance of the Stream Buffer DSP, which already assigns the DSP ( will be called automatically). + + Channel that the DSP is being applied to. + The priority of the DSP, which determines it's position in the DSP chain - DSPs with higher priority are called before those with lower. + The DSP is automatically assigned by this constructor! + Use to remove the DSP (you can (re)assign the DSP at any time again by calling ). + + + + + Clears the internal buffer (zeros all elements) and resets the buffer pointer. + + + Use this method e.g. when you paused/stoped the original . + + + + + Occures when the has been changed. + + NOT for direct use in your application! + + + + Occures when the method was called. + Actually clears the internal copy buffer. + + NOT for direct use in your application! + + + + Occures when the method was called. + Actually creates the custom stream here. + + NOT for direct use in your application! + + + + Occures when the method was called. + Actually frees the custom stream here. + + NOT for direct use in your application! + + + + User defined DSP callback function which does the stream copy operation. Not for direct use in your application! + + The DSP handle. + Channel that the DSP is being applied to. + The buffer to apply the DSP to. The sample data is as follows: 8-bit samples are unsigned, 16-bit samples are signed, 32-bit floating-point samples range from -1 to +1 (not clipped, so can actually be outside this range). + The number of BYTES to process. + The user instance data given (see ). + Not for direct use in your application! + + + + Returns the name of the DSP. + + The name of the DSP. + + + + Gets the buffered BASS stream (the created custom stream). + + You might use this stream channel handle to call or in order to retrive the FFT or level data. + + + + + Gets the channel flags of the being used. + + The channel flags are actually being the same as from the original , but if you have FLOATDSP enabled the FLOAT flag will be added automatically. + In addition will always be a decoding stream! + + + + Gets or Sets a buffered output BASS stream to synchronize the position with (0 = use a non-synchronized direct buffer). + + When not setting this property (or setting to 0) the internal buffer position will not be synchronized, which means the buffer reflects the immediate sample data as received in the DSP. + This is perfect, if you want to create an exact shadow copy (clone) of the decoding . In this case use the member to e.g. feed it to another + + + + + Gets or Sets, if the should be buffered or not (default is ). + + If set to , the position will be buffered. This option is useful, if you want to use it with a buffered output stream. + If set to the will not be buffered, which is usefull when used with unbuffered outputs (e.g. ASIO). + + + + Gets or Sets the buffer length in milliseconds to be used (between 1 and 5000). + + The buffer length needs to be as big as the BASS_CONFIG_BUFFER setting used to create the . + Normally there is no need set this value, since it will be calculated accordingly to the current BASS_CONFIG_BUFFER setting. + But this implies, that you haven't changed the BASS_CONFIG_BUFFER between the creation of the stream an using this DSP. + So if you have changed the BASS_CONFIG_BUFFER setting in the meantime, you must provide the new BASS_CONFIG_BUFFER size. + + + + + Gets the buffer length in bytes which is being used. + + + This is the translated value. + + + + + Gets or Sets the current buffer position in bytes. + + This member is maintained automatically depending on the property and the current buffer state. + So normally there is no need to modify this value. However if you have a real need you might do so. + + + + + Enables streaming of audio content to the internet. + + + To setup broadcast streaming you first need to create an instance of a class, which is derived from the class (e.g. or ). + These classes will contain all necessary configuration data (e.g. server address an port, username and password, station description etc., as well as an instance, which defines the target broadcasting encoder format). + The BroadCast class support manual streaming (e.g. in your own or ) as well as + automatic streaming. Automatic streaming is implemented internally also via a user DSP. + If you want to broadcast to multiple outputs (multiple servers) you need to create an instance for each output seperately. + + + The following example uses the generic Encoder-Framework with the generic StreamingServer-Framework + to implement streaming of any recording data (here uing LAME MP3 encoding to a SHOUTcast server): + + private int _recHandle; + private BroadCast _broadCast; + ... + _recHandle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_DEFAULT, null, 0); + ... + // create an encoder instance (e.g. for MP3 use EncoderLAME): + EncoderLAME lame = new EncoderLAME(_recHandle); + lame.InputFile = null; //STDIN + lame.OutputFile = null; //STDOUT + lame.LAME_Bitrate = (int)EncoderLAME.BITRATE.kbps_56; + lame.LAME_Mode = EncoderLAME.LAMEMode.Mono; + lame.LAME_TargetSampleRate = (int)EncoderLAME.SAMPLERATE.Hz_22050; + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality; + + // create a StreamingServer instance (e.g. SHOUTcast) using the encoder: + SHOUTcast shoutcast = new SHOUTcast(lame); + shoutcast.ServerAddress = "localhost"; + shoutcast.ServerPort = 8000; + shoutcast.Password = "changeme"; + shoutcast.PublicFlag = true; + + // use the BroadCast class to control streaming: + _broadCast = new BroadCast(shoutcast); + _broadCast.AutoReconnect = true; + _broadCast.Notification += new BroadCastEventHandler(OnBroadCast_Notification); + _broadCast.AutoConnect(); + + private void OnBroadCast_Notification(object sender, BroadCastEventArgs e) + { + // Note: this method might be called from another thread (non UI thread)! + if (_broadCast == null) + return; + if (_broadCast.IsConnected) + { + // we are connected... + } + else + { + // we are not connected... + } + } + + + Private _recHandle As Integer + Private _broadCast As BroadCast + ... + _recHandle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_DEFAULT, Nothing, 0) + ... + ' create an encoder instance (e.g. for MP3 use EncoderLAME): + Dim lame As New EncoderLAME(_recHandle) + lame.InputFile = Nothing 'STDIN + lame.OutputFile = Nothing 'STDOUT + lame.LAME_Bitrate = CInt(EncoderLAME.BITRATE.kbps_56) + lame.LAME_Mode = EncoderLAME.LAMEMode.Mono + lame.LAME_TargetSampleRate = CInt(EncoderLAME.SAMPLERATE.Hz_22050) + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality + + ' create a StreamingServer instance (e.g. SHOUTcast) using the encoder: + Dim shoutcast As New SHOUTcast(lame) + shoutcast.ServerAddress = "localhost" + shoutcast.ServerPort = 8000 + shoutcast.Password = "changeme" + shoutcast.PublicFlag = True + + ' use the BroadCast class to control streaming: + _broadCast = New BroadCast(shoutcast) + _broadCast.AutoReconnect = True + AddHandler _broadCast.Notification, AddressOf OnBroadCast_Notification + _broadCast.AutoConnect() + + Private Sub OnBroadCast_Notification(sender As Object, e As BroadCastEventArgs) + ' Note: this method might be called from another thread (non UI thread)! + If _broadCast Is Nothing Then + Return + End If + If _broadCast.IsConnected Then + ' we are connected... + Else + ' we are not connected... + End If + End Sub + + + + + + Default constructor not allowed. + + + + + Creates an instance of the broadcasting class using the specified streaming server. + + Instance of a streaming server class to use (containing the configuration and parameter data). + In order to create a instance use one of the implementations (e.g. or ). + + + + Connects automatically to a broadcast server (performs a and ). + + on success, else (see or for details). + + If the has set the flag to , the will handle any communication via . + If the has set the flag to , the following will be handled: + Prior to the an internal encoder callback will be created. + The internal encoder callback is created using . + This internal callback will already handle the , and automatically for you. + If already connected, this method will first from the , which might result in stopping the underlying . + If the channel handle (as defined in the ) is already playing, it will be shortly paused during the setup and resumed when done. + Please note, that some methods should NOT be used, if in automatic mode: , , and ! + Note: If you have set the property to this call will automatically try to reconnect even if this method returns ! + + + + + Connects manually to a broadcast server (performs a and ). + + on success, else (see or for details). + The automatic reconnect settings ( and ) will also work with a manual connection. + But, you must create and handle your own callback and call manually! + If already connected, this method will first from the , which might result in stopping the underlying . + If the channel handle (as defined in the ) is already playing, it will be shortly paused during the setup and resumed when done. + Note: If you have set the property to this call will automatically try to reconnect even if this method returns ! + + + This example demonstrates manual broadcasting: + + private BroadCast _broadCast; + private ENCODEPROC _myEncProc; + ... + // create your encoder (using a recording handle) + EncoderLAME lame = new EncoderLAME(_recHandle); + + // create an streaming server instance + SHOUTcast shoutcast = new SHOUTcast(lame); + + // create the broadcast instance + _broadCast = new BroadCast(shoutcast); + _broadCast.AutoReconnect = true; + _broadCast.Notification += new BroadCastEventHandler(OnBroadCast_Notification); + + // create your encoder callback + _myEncProc = new ENCODEPROC(MyEncodingCallback); + // start the encoder (paused) + _broadCast.StartEncoder(_myEncProc, IntPtr.Zero, true); + // now connect to start your broadcast + _broadCast.Connect(); + // and really start the encoder + _broadCast.Server.Encoder.Pause(false); + ... + + // your broadcast encoder callback implementation + private void MyEncodingCallback(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + // here we receive the encoded data back (manual mode) + if ( _broadCast.IsConnected ) + { + _broadCast.SendData(buffer, length); + } + } + + private void OnBroadCast_Notification(object sender, BroadCastEventArgs e) + { + if (e.EventType == BroadCastEventType.EncoderRestartRequired) + _broadCast.StartEncoder(_myEncProc, 0); + + if (!_broadCast.IsConnected) + { + // connection lost + } + } + + + Private _broadCast As BroadCast + Private _myEncProc As ENCODEPROC + ... + ' create your encoder (using a recording handle) + Dim lame As New EncoderLAME(_recHandle) + + ' create an streaming server instance + Dim shoutcast As New SHOUTcast(lame) + + ' create the broadcast instance + _broadCast = New BroadCast(shoutcast) + _broadCast.AutoReconnect = True + AddHandler _broadCast.Notification, AddressOf OnBroadCast_Notification + + ' create your encoder callback + _myEncProc = New ENCODEPROC(AddressOf MyEncodingCallback) + ' start the encoder (paused) + _broadCast.StartEncoder(_myEncProc, IntPtr.Zero, True) + ' now connect to start your broadcast + _broadCast.Connect() + ' and really start the encoder + _broadCast.Server.Encoder.Pause(False) + ... + + ' your broadcast encoder callback implementation + Private Sub MyEncodingCallback(handle As Integer, channel As Integer, + buffer As IntPtr, length As Integer, user As IntPtr) + ' here we receive the encoded data back (manual mode) + If _broadCast.IsConnected Then + _broadCast.SendData(buffer, length) + End If + End Sub + + Private Sub OnBroadCast_Notification(sender As Object, e As BroadCastEventArgs) + If e.EventType = BroadCastEventType.EncoderRestartRequired Then + _broadCast.StartEncoder(_myEncProc, 0) + End If + + If Not _broadCast.IsConnected Then + ' connection lost + End If + End Sub + + + + + + Disconnects from the broadcast server calling (also stops the encoder using ). + + on success (not connected), else (connection status unknown, see or for details). + This method disconnects no matter if you started broadcasting in the automatic mode (via ) or manually (via ). + Note: If you stop or free the underlying stream channel you must also call this method in order to disconnect from the server. + Caution: Disconnecting will in any case also stop the underlying server encoder in use ( will be called!). + So if you started broadcasting in the manual mode (via ) you need to manually start your encoder again. + If you have enabled the feature a event will be raised. + If this method returns , check the , it might be the case, that you are still connected (e.g. if the encoder could not be stopped)! + Once disconnected successfully, the feature will also be disabled (no further connect retries will be made). + You need to start broadcasting again via or in order to restart. + + + + + Starts the underlying encoder (see ). + + Optional callback function to receive the encoded data. + To have the encoded data received by a callback function, the encoder needs to be told to output to STDOUT (instead of a file), so must return true. + User instance data to pass to the callback function. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Return , if the encoder was successfully started - else is returned (see or for details). + + Do NOT call this method, if you are in , since the encoder will be started automatically in this case. + If the encoder was already started, this method anyhow returns - however no event will be raised in this case. + If you manually, your must call manually as well, see the example below. + + + This example demonstrates a user defined ENCODEPROC: + + private BroadCast _broadCast; + private ENCODEPROC _myEncProc; + ... + // create your encoder (using a recording handle) + EncoderLAME lame = new EncoderLAME(_recHandle); + + // create an streaming server instance + SHOUTcast shoutcast = new SHOUTcast(lame); + + // create the broadcast instance + _broadCast = new BroadCast(shoutcast); + _broadCast.AutoReconnect = true; + _broadCast.Notification += new BroadCastEventHandler(OnBroadCast_Notification); + + // create your encoder callback + _myEncProc = new ENCODEPROC(MyEncodingCallback); + // start the encoder (paused) + _broadCast.StartEncoder(_myEncProc, IntPtr.Zero, true); + // now connect to start your broadcast + _broadCast.Connect(); + // and really start the encoder + _broadCast.Server.Encoder.Pause(false); + ... + + // your broadcast encoder callback implementation + private void MyEncodingCallback(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + // here we receive the encoded data back (manual mode) + if ( _broadCast.IsConnected ) + { + _broadCast.SendData(buffer, length); + } + } + + private void OnBroadCast_Notification(object sender, BroadCastEventArgs e) + { + if (e.EventType == BroadCastEventType.EncoderRestartRequired) + _broadCast.StartEncoder(_myEncProc, 0); + + if (!_broadCast.IsConnected) + { + // connection lost + } + } + + + Private _broadCast As BroadCast + Private _myEncProc As ENCODEPROC + ... + ' create your encoder (using a recording handle) + Dim lame As New EncoderLAME(_recHandle) + + ' create an streaming server instance + Dim shoutcast As New SHOUTcast(lame) + + ' create the broadcast instance + _broadCast = New BroadCast(shoutcast) + _broadCast.AutoReconnect = True + AddHandler _broadCast.Notification, AddressOf OnBroadCast_Notification + + ' create your encoder callback + _myEncProc = New ENCODEPROC(AddressOf MyEncodingCallback) + ' start the encoder (paused) + _broadCast.StartEncoder(_myEncProc, IntPtr.Zero, True) + ' now connect to start your broadcast + _broadCast.Connect() + ' and really start the encoder + _broadCast.Server.Encoder.Pause(False) + ... + + ' your broadcast encoder callback implementation + Private Sub MyEncodingCallback(handle As Integer, channel As Integer, + buffer As IntPtr, length As Integer, user As IntPtr) + ' here we receive the encoded data back (manual mode) + If _broadCast.IsConnected Then + _broadCast.SendData(buffer, length) + End If + End Sub + + Private Sub OnBroadCast_Notification(sender As Object, e As BroadCastEventArgs) + If e.EventType = BroadCastEventType.EncoderRestartRequired Then + _broadCast.StartEncoder(_myEncProc, 0) + End If + + If Not _broadCast.IsConnected Then + ' connection lost + End If + End Sub + + + + + + Stops the + + , if the encoder was stopped successfully, else is returned (see or for details). + Please note that, if is returned, the will still be active. + If you are handling broadcasting manually (by using ), it is a good idea to stop the encoder whenever you are not connected anymore. + You might check the status of the broadcast connection by asking for the or by subscribing to the event handler. + If the encoder was already stopped, this method returns - however no event will be raised in this case. + + + + + Sends encoded sample data manually to the broadcast server (e.g. the data as received in an own ). + + The pointer to the encoded buffer data (as given by to callback). + The length of the buffer data (as given by to callback). + on success, else (see or for details). + If an error occures the connection will be closed automatically (using ). + In this case the feature (if enabled) will try a reconnect after . + + + + Updates the title of the playing song on a broadcast server. + + The new song title to set (if or empty will be returned). + The optional song url to go along with the title (only for SHOUTcast - else ). + on success, else (see or for details). + This method can be used for both the manual and the automatic connection mode. + + + + Updates the title of the playing song on a broadcast server. + + The instance to use to set the new song title (if or empty will be returned). + The optional song url to go along with the title (only for SHOUTcast - else ). + on success, else (see or for details). + This method can be used for both the manual and the automatic connection mode. + + + + Returns the number of listeners currently connected. + + The optional admin password to use (=use default). + The current number of listeners (or -1 if not available). + Some implementations might not be able to retrieve the current listener count, in which case -1 would be returned. + However, the following servers should be supported: SHOUTcast, ICEcast, WMAcast (if not using a publishing point). + + + + + Returns the XML stats of the server. + + An optional password to use (should be set to to use the default publish password). + The string representing the XML formatted statistics (or on error/not available). + Some implementations might not be able to retrieve an XML statistic, in which case would be returned. + However, the following servers should be supported: SHOUTcast, ICEcast, WMAcast. + + + + + Event handler used to notify that the BroadCast status has changed or that a BroadCast event has occurred. + + It is a good idea to subscribe to this event handler before calling or . + The properties and might be used to supress sending certain events. + The contains a which allows you to react to all possible scenarios and to log all these events. + Note: This implementation ensures, that the event will be executed in the main thread the subscriber executes in! + So when subscribing to this event from UI thread, the specified event delegate will also be called in that UI thread. + When using a server whose UseBASS property is set to (which is the default) the 'DataSend' notification will not be raised. + + + + + Returns the streaming server interface which is used with this instance. + + + + + Connected to the server? (=connected). + + Sending encoded data to the via should only be performed, if connected to the + and the has the flag set to ! + + + + Is the server started? (=started). + + This property might also return if the status is not connected in case you set to true. + + + + Gets the current broadcast status. + + + + + Gets if the automatic mode was used (, if was called, else meaning was used instead). + + When the automatic mode is used, the following is handled directly by this class and does not need to be handled manually: + Setup of an internal encoder callback procedure and sending of the encoded data to the (either internally or via ). + So the only task you need to handle is title updates manually when in automatic mode. + Please note, that some methods should NOT be used, if in automatic mode: , , and ! + + + + + Gets or Sets if the broadcast connection should automatically be reconnected in case of a connection or encoder error (default=). + + The auto connect feature can be used for both and . + When AutoReconnect was set to , the following will be checked automatically: + 1. Is the encoder still active? - if not, restart encoder, if in . + 2. Are we still connected to the ? - if not, reconnect to the . + This means, that if you are NOT in , you need to restart your manually. + You can do so by subscribing to the event handler and react on the event and then call again. + Please note, that the encoder will automatically be stopped, if a reconnect to the server was not successful! + + + + + Gets or Sets the reconnect timeout in seconds (default is 5sec.). + + The auto connect feature can be used for both and . + The timeout period must be between 1 and 86400 seconds. + Changing the reconnect timeout takes immediate effect. + + + + + Gets or Sets, if the event will be raised when subscribed to the event handler (default is ). + + Note: If the has the flag set to this property will have no effect. + A with will be unable to to report the number of bytes send to the server. + + + + Gets or Sets, if the event will be raised when subscribed to the event handler and is enabled (default is ). + + + + + Returns the total number of bytes send to the server during a broadcast. + + + If the value reaches the maximum (Int64.MaxValue) it will be wrapped around and reset to 0 (zero). + + + + + Returns the total online connection time (for how long the broadcast is already running since it was connected). + + This value is only correct, if is resp. the broadcast is CONNECTED. + + + + List of all possible broadcast status. + + + + + Not connected. + + + + + Connected to the broadcast server. + + + + + Connection status is unknown. + + + + + Definition of the event handler. + + Set to the object instance that raised the event. + An instance of the event args containing the event details. + + This definition complies with the .NET Framework's standard for event handlers. + + + + + Types of event that has occurred with the class. + + + A variable of this type is passed inside the object + for the event. + + + + + A connection to the server was successfully established. + Object data: DateTime (start of connection). + + + + + The server was disconnected (either by user request or due to a connection error). + Object data: DateTime (time of disconnect). + + + + + An error occurred during the disconnect (the server might still be connected). + Object data: DateTime (time of disconnect). + + + + + The connection was lost (can only be discovered at ). + Object data: DateTime (time of lost connection). + + + + + A connection to the server could not be established (will only be raised at or ). + Object data: DateTime (time of lost connection). + + + + + A reconnect will be tried (after the ). + Object data: DateTime (time of reconnect try). + + + + + A reconnect was unsuccessfully tried. + Object data: DateTime (time of unsuccessful reconnect try). + + + + + The encoder was started successfully (will only be raised in ). + Object data: (the encoder instance which needs to be restarted). + + + + + The encoder could not be started (will only be raised in ). + Object data: (the encoder instance which needs to be restarted). + + + + + The encoder was stopped (will only be raised in ). + Object data: (the encoder instance which needs to be restarted). + + + + + The encoder could not be stopped (will only be raised during - the disconnect might fail and might still be connected). + Object data: (the encoder instance which needs to be restarted). + + + + + The underlying encoder is not active and needs to be started again. + Object data: (the encoder instance which needs to be restarted). + + + + + All data was send to the server successfully (will only be raised when is and is set to ). + Object data: long (number of bytes send). + + + + + Data was send to the server, but not all data was send (will only be raised when is set to ). + Object data: int (number of bytes not send). + + + + + The broadcast connection is alive and streaming is active (will only be raised when is and is and is set to ). + Object data: DateTime (time of is alive signal). + + + + + The song title was updated. + Object data: string (song title). + + + + + The song title was not updated. + Object data: string (song title). + + + + + A reconnect was successfull. + Object data: DateTime (time of reconnect). + + + + + EventArgs class to be passed as the second parameter of a event handler. + + + This class provides all the information relevant to an event which might occur to a class. + + + + + Initializes a new instance of the BroadCastEventArgs class by initializing all of its properties. + + The type of event which occurred (see ). + Some data which should be passed along with the notification event. + + + + Gets the type of event which occurred. + + + + + Gets the object data which was passed along with the event. + + + + + Gets the date and time when the event occurred. + + + + + Defines a generalized streaming server class interface that a class must implement. + + This interface is for example used in the constructor of a instance to specify which server should be used. + + + + Connects to a streaming server. + + on success, else (see or for details). + A server connect should only be successfull, if the underlying encoder was started. + + + + Disconnects to a streaming server. + + on success, else (see or for details). + + + + Performs a login and/or init of the streaming server. + + on success, else (see or for details). + When the login was successfully made, you should set the to and the to String.Empty. + + + + Sends encoded sample data (manually) to the streaming server (e.g. the data as received in an own ). + + The pointer to the encoded buffer data (as given by to callback). + The length of the buffer data (as given by to callback). + The number of bytes send to the server (or -1, if no bytes could be send (see or for details). + If an error occures the connection should be closed automatically (using ). + + + + Updates the title song and/or url of the streaming server. + + The title of the song which should be updated. + The url which should be updated along with the title (or ). + on success, else (see or for details). + + + + Updates the song title and/or url of the streaming server. + + The instance to use to update the song. + The url which should be updated along with the title (or ). + on success, else (see or for details). + + + + Returns the number of listeners currently connected. + + The optional admin password to use (=use default). + The current number of listeners (or -1 if not available). + + + + Returns the XML stats of the server. + + The optional admin password to use (=use default). + The string representing the XML formatted statistics (or on error/not available). + + + + Gets if native BASS should be used to connect and stream to the server. + + + If set to (see constructor) native BASSenc will handle all TCP socket and cast communication. + This should be the more secure and preferred option, however in this mode it is not possible to use the method manually! + If set to an internal .Net TCP socket connection will be used and manual feed of encoded sample data via is possible. + + + + + Returns , if connected to a streaming server - else . + + Normally it is sufficient to return once a was successful. + However, if the server implementation also requires a this method should only return , if also the was successful. + + + + Returns the encoder interface which is used with this instance. + + + + + Gets or Sets the last streaming error. + + + + + Gets or Sets the last streaming error message. + + + + + Gets or Sets the current/last song title. + + + + + Gets or Sets the current/last song url. + + + + + Gets or Sets if title updates (via ) should in any case use UTF-8 (default is ). + + + Depending on the streaming server and stream format being used title updates might be performed using Windows-1252, Latin1 or UTF-8 encoding by default. + When setting this property to you can force title updates to be performed using UTF-8 encoding. + Note: Only set this property to if you are sure, that the streaming server supports title updates in UTF-8! + The default behaviour (when this property is set to ) is as followed: + + Streaming ServerTitle Updates in + SHOUTcastWindows-1252 codepage (Latin1) + ICEcastOGG streams: UTF-8non-OGG streams: ISO-8859-1 (Latin1) + WMAcastUTF-8 + + + + + + + Base class for all streaming server classes (e.g. or ). + + This base class is not intended for direct use, but defines all abstract properties and methods which needs to be implemented by an actual streaming server class. + A derived class must implement: , , , , and . + The properties , and have been already implemented. + You might use this base class to derive your own streaming server implementations. + If an instance of a derived class is being disposed, an already created connection to a streaming server will automatically be closed (using ) and an will be stopped, if active. + + + + This example shows a basic implementation of an own streaming server class: + + public class MyOwnServer : StreamingServer + { + // Constructor + public MyOwnServer(IBaseEncoder encoder, bool useBASS) : base(encoder, useBASS) + { + // validity check + if (encoder.EncoderType != BASSChannelType.BASS_CTYPE_STREAM_MP3 && + encoder.EncoderType != BASSChannelType.BASS_CTYPE_STREAM_AAC) + throw new Exception( "Invalid EncoderType (only MP3 and AAC is supported)!" ); + } + + private Socket _socket = null; + private bool _loggedIn = false; + private byte[] _data = null; + private object _lock = false; + public string ServerAddress = "localhost"; + public int ServerPort = 8000; + + public override bool IsConnected + { + get + { + if (_socket != null) + return _socket.Connected && _loggedIn; + else + return false; + } + } + + public override bool Connect() + { + // check the encoder + if (!Encoder.IsActive) + { + LastError = STREAMINGERROR.Error_EncoderError; + LastErrorMessage = "Encoder not active!"; + return false; + } + // close any connections, if still open + if (_socket != null && _socket.Connected) + { + _socket.Close(); + _socket = null; + } + // create a connection at port+1 + _socket = CreateSocket( ServerAddress, ServerPort+1 ); + return (_socket != null && _socket.Connected); + } + + public override bool Disconnect() + { + bool ok = false; + try + { + _socket.Close(); + } + catch { } + finally + { + if (_socket != null && _socket.Connected) + { + LastError = STREAMINGERROR.Error_Disconnect; + LastErrorMessage = "Winsock error: " + + Convert.ToString(System.Runtime.InteropServices.Marshal.GetLastWin32Error()); + } + else + { + ok = true; + _socket = null; + _loggedIn = false; + } + } + return ok; + } + + public override bool Login() + { + if (_socket == null) + { + LastError = STREAMINGERROR.Error_NotConnected; + LastErrorMessage = "Not connected to server."; + return false; + } + bool ok = false; + if ( MyLogin() ) + { + if ( MyInit() ) + { + ok = true; + _loggedIn = true; + LastError = STREAMINGERROR.Ok; + LastErrorMessage = String.Empty; + } + else + { + LastError = STREAMINGERROR.Error_Login; + LastErrorMessage = "Server could not be initialized."; + } + } + else + { + LastError = STREAMINGERROR.Error_Login; + LastErrorMessage = "Invalid username or password."; + } + return ok; + } + + public override int SendData(IntPtr buffer, int length) + { + if (buffer == IntPtr.Zero || length == 0) + return 0; + int sendData = -1; + try + { + lock (_lock) + { + // dynamic buffer allocation + if (_data == null || _data.Length < length) + _data = new byte[length]; + Marshal.Copy(buffer, _data, 0, length); + sendData = _socket.Send( _data, 0, length, SocketFlags.None ); + if (sendData < 0) + { + LastError = STREAMINGERROR.Error_SendingData; + LastErrorMessage = String.Format( "{0} bytes not send.", length); + Disconnect(); + } + else if (sendData != length) + { + LastError = STREAMINGERROR.Warning_LessDataSend; + LastErrorMessage = String.Format( "{0} of {1} bytes send.", sendData, length); + } + } + } + catch (Exception e) + { + LastError = STREAMINGERROR.Error_SendingData; + LastErrorMessage = e.Message; + sendData = -1; + Disconnect(); + } + return sendData; + } + + public override bool UpdateTitle(string song, string url) + { + SongTitle = song; + return MyUpdateTitle(song); + } + + private Socket CreateSocket(string serveraddress, int port) + { + Socket socket = null; + IPHostEntry hostEntry = null; + try + { + // Get host related information + hostEntry = Dns.GetHostEntry(serveraddress); + // Loop through the AddressList to obtain the supported AddressFamily. + foreach(IPAddress address in hostEntry.AddressList) + { + try + { + IPEndPoint ipe = new IPEndPoint(address, port); + Socket tempSocket = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + tempSocket.Connect(ipe); + if (tempSocket.Connected) + { + socket = tempSocket; + break; + } + else + { + continue; + } + } + catch (Exception e) + { + LastError = STREAMINGERROR.Error_CreatingConnection; + LastErrorMessage = e.Message; + socket = null; + } + } + } + catch (Exception e) + { + LastError = STREAMINGERROR.Error_ResolvingServerAddress; + LastErrorMessage = e.Message; + socket = null; + } + return socket; + } + + private bool MyLogin() + { + if (_socket == null) + return false; + // e.g. send password here using the "_socket" + ... + } + + private bool MyInit() + { + if (_socket == null) + return false; + // e.g. send some init data to the server here using the "_socket" + ... + } + + private bool MyUpdateTitle(string song) + { + bool ok = false; + Socket socket = null; + try + { + socket = CreateSocket( ServerAddress, ServerPort ); + if (socket != null) + { + // send the song title using the created "socket" + ... + ok = true; + } + } + catch { } + finally + { + // disconnect + if (socket != null) + { + socket.Close(); + socket = null; + } + } + return ok; + } + } + + + Public Class MyOwnServer Inherits StreamingServer + + ' Constructor + Public Sub New(encoder As IBaseEncoder, useBASS As Boolean) MyBase.New(encoder, useBASS) + ' validity check + If encoder.EncoderType <> BASSChannelType.BASS_CTYPE_STREAM_MP3 AndAlso + encoder.EncoderType <> BASSChannelType.BASS_CTYPE_STREAM_AAC Then + Throw New Exception("Invalid EncoderType (only MP3 and AAC is supported)!") + End If + End Sub + + Private _socket As Socket = Nothing + Private _loggedIn As Boolean = False + Private _data As Byte() = Nothing + Private _lock As Object = False + Public ServerAddress As String = "localhost" + Public ServerPort As Integer = 8000 + + Public Overrides ReadOnly Property IsConnected() As Boolean + Get + If Not (_socket Is Nothing) Then + Return _socket.Connected AndAlso _loggedIn + Else + Return False + End If + End Get + End Property + + Public Overrides Function Connect() As Boolean + ' check the encoder + If Not Encoder.IsActive Then + LastError = STREAMINGERROR.Error_EncoderError + LastErrorMessage = "Encoder not active!" + Return False + End If + ' close any connections, if still open + If Not (_socket Is Nothing) AndAlso _socket.Connected Then + _socket.Close() + _socket = Nothing + End If + ' create a connection at port+1 + _socket = CreateSocket(ServerAddress, ServerPort + 1) + Return Not (_socket Is Nothing) AndAlso _socket.Connected + End Function + + Public Overrides Function Disconnect() As Boolean + Dim ok As Boolean = False + Try + _socket.Close() + Catch + Finally + If Not (_socket Is Nothing) AndAlso _socket.Connected Then + LastError = STREAMINGERROR.Error_Disconnect + LastErrorMessage = "Winsock error: " + + Convert.ToString(System.Runtime.InteropServices.Marshal.GetLastWin32Error()) + Else + ok = True + _socket = Nothing + _loggedIn = False + End If + End Try + Return ok + End Function + + Public Overrides Function Login() As Boolean + If _socket Is Nothing Then + LastError = STREAMINGERROR.Error_NotConnected + LastErrorMessage = "Not connected to server." + Return False + End If + Dim ok As Boolean = False + If MyLogin() Then + If MyInit() Then + ok = True + _loggedIn = True + LastError = STREAMINGERROR.Ok + LastErrorMessage = [String].Empty + Else + LastError = STREAMINGERROR.Error_Login + LastErrorMessage = "Server could not be initialized." + End If + Else + LastError = STREAMINGERROR.Error_Login + LastErrorMessage = "Invalid username or password." + End If + Return ok + End Function + + Public Overrides Function SendData(buffer As IntPtr, length As Integer) As Integer + If buffer = IntPtr.Zero OrElse length = 0 Then + Return 0 + End If + Dim sendData As Integer = -1 + Try + SyncLock _lock + ' dynamic buffer allocation + If _data Is Nothing OrElse _data.Length < length Then + _data = New Byte(length) {} + End If + Marshal.Copy(buffer, _data, 0, length) + sendData = _socket.Send(_data, 0, length, SocketFlags.None) + If sendData < 0 Then + LastError = STREAMINGERROR.Error_SendingData + LastErrorMessage = [String].Format("{0} bytes not send.", length) + Disconnect() + Else + If sendData <> length Then + LastError = STREAMINGERROR.Warning_LessDataSend + LastErrorMessage = [String].Format("{0} of {1} bytes send.", sendData, length) + End If + End If + End SyncLock + Catch e As Exception + LastError = STREAMINGERROR.Error_SendingData + LastErrorMessage = e.Message + sendData = -1 + Disconnect() + End Try + Return sendData + End Function + + Public Overrides Function UpdateTitle(song As String) As Boolean + SongTitle = song + Return MyUpdateTitle(song) + End Function + + Private Function CreateSocket(serveraddress As String, port As Integer) As Socket + Dim socket As Socket = Nothing + Dim hostEntry As IPHostEntry = Nothing + Try + ' Get host related information + hostEntry = Dns.GetHostEntry(serveraddress) + ' Loop through the AddressList to obtain the supported AddressFamily. + Dim address As IPAddress + For Each address In hostEntry.AddressList + Try + Dim ipe As New IPEndPoint(address, port) + Dim tempSocket As New Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp) + tempSocket.Connect(ipe) + If tempSocket.Connected Then + socket = tempSocket + Exit ForEach + Else + GoTo ContinueForEach1 + End If + Catch e As Exception + LastError = STREAMINGERROR.Error_CreatingConnection + LastErrorMessage = e.Message + socket = Nothing + End Try + ContinueForEach1: + Next address + Catch e As Exception + LastError = STREAMINGERROR.Error_ResolvingServerAddress + LastErrorMessage = e.Message + socket = Nothing + End Try + Return socket + End Function + + Private Function MyLogin() As Boolean + If _socket Is Nothing Then + Return False + End If + ' e.g. send password here using the "_socket" + ... + End Function + + Private Function MyInit() As Boolean + If _socket Is Nothing Then + Return False + End If + ' e.g. send some init data to the server here using the "_socket" + ... + End Function + + Private Function MyUpdateTitle(song As String) As Boolean + Dim ok As Boolean = False + Dim socket As Socket = Nothing + Try + socket = CreateSocket(ServerAddress, ServerPort) + If Not (socket Is Nothing) Then + ' send the song title using the created "socket" + ... + ok = True + End If + Catch + Finally + ' disconnect + If Not (socket Is Nothing) Then + socket.Close() + socket = Nothing + End If + End Try + Return ok + End Function + + End Class + + + + + + Default constructor, creating an instance for a streaming server implementation (using BASSenc as the default processor). + + The encoder interface which should be used with this streaming server. + This overload will set the property to . + No specified. + The could not be found. Make sure the encoder (.exe) is present. + + + + Default constructor, creating an instance for a streaming server implementation. + + The encoder interface which should be used with this streaming server. + , if BASSenc should be used to handle all cast server handling. , if the internal implementation should be used. + No specified. + The could not be found. Make sure the encoder (.exe) is present. + + + + Implement IDisposable. + + Do not make this method virtual. A derived class should not be able to override this method. + + + + Finalization code. + + This destructor will run only if the Dispose method does not get called. + It gives your base class the opportunity to finalize. Do not provide destructors in types derived from this class. + + + + Connects to a streaming server. + + on success, else (see or for details). + + + + Disconnects from a streaming server. + + on success, else (see or for details). + A server connect should only be successfull, if the underlying encoder was started. + + + + Performs a login to and/or initializes the streaming server. + + on success, else (see or for details). + If a server doesn't not need to handle a particular login or initialization, you might simply return in the implementation. + However, when the login was successfully made, you should set the to and the to String.Empty. + + + + Sends encoded sample data (manually) to the streaming server (e.g. the data as received in an own ). + + The pointer to the encoded buffer data (as given by to callback). + The length of the buffer data (as given by to callback). + The number of bytes send to the server (or -1, if no bytes could be send (see or for details). + If an error occures the connection will be closed automatically (using ). + + + + Updates the song title of the streaming server. + + The song title to use. + The url which should be updated along with the title (or ). + on success, else (see or for details). + + + + Updates the song title of the streaming server. + + The instance to use to update the song title. + The url which should be updated along with the title (or ). + on success, else (see or for details). + + + + Returns the number of listeners currently connected. + + The optional admin password to use (=use default). + The current number of listeners (or -1 if not available). + + + + Returns the XML stats of the server. + + The optional admin password to use (=use default). + The string representing the XML formatted statistics (or on error/not available). + + + + Gets if native BASSenc should be used to connect and stream to the server (as specified in the constructor). + + + If set to native BASSenc will handle all TCP socket and cast communication. + This should be the more secure and preferred option, however in this mode it is not possible to use the method manually! + If set to an internal .Net TCP socket connection will be used and manual feed of encoded sample data via is possible. + + + + + The current/last song title. + + + + + The current/last song url. + + + + + Gets or Sets if title updates (via ) should in any case use UTF-8 (default is ). + + + Depending on the streaming server and stream format being used title updates might be performed using Windows-1252, Latin1 or UTF-8 encoding by default. + When setting this property to you can force title updates to be performed using UTF-8 encoding. + Note: Only set this property to if you are sure, that the streaming server supports title updates in UTF-8! + The default behaviour (when this property is set to ) is as followed: + + Streaming ServerTitle Updates in + SHOUTcastWindows-1252 codepage (Latin1) + ICEcastOGG streams: UTF-8non-OGG streams: ISO-8859-1 (Latin1) + WMAcastUTF-8 + + + + + + + Returns , if connected to a boadcast server - else . + + Normally it is sufficient to return once a was successful. + However, if the server implementation also requires a this method should only return , if also the was successful. + + + + Returns the encoder interface which is used with this instance. + + + + + Gets or Sets the last streaming error. + + + + + Gets or Sets the last streaming error message. + + + + + List of all possible streaming errors. + + + + + All OK. + + + + + The server address could not be resolved (DNS error). + + + + + A TCP socket connection to the server could not be established (TCP error). + + + + + The data could not be send to the server (TCP error). + The server will automatically be disconnected. + + + + + The encoder could not be started or is inactive. + + + + + Access was denied (check username and password). + + + + + An error occurred during a disconnect (disconnect failed, still connected). + + + + + A connection to the server was not established. + + + + + Not all data could not be send to the server (less data send). + The server will automatically be disconnected. + + + + + An unknown error occurred. + + + + + SHOUTcast streaming parameter class. + To be used when creating an instance of the class. + + An instance of the class will providing all necessary setup and configuration data in order to connect to a SHOUTcast v1 or v2 server. + For more information about the SHOUTcast streaming parameters take a look to the www.shoutcast.com documentation. + Note: in order to use the SHOUTcast v2 protocol the property must be set! + + + + + Creates an instance for a SHOUTcast configuration parameter setting. + + The output encoder instance to be used. + An instance of this class is needed in order to create a instance. + Please note, that you need an appropriate encoder for SHOUTcast streaming. For MP3 streaming we recommend using the latest stable version of LAME (see ). + When streaming in AACplus format an external encoder is needed as well, which accepts pcm data from STDIN and is able to send it's encoded data to STDOUT. + As of today the only 'free' AACplus encoders comes with Winamp - you might use the 'enc_aacPlus.exe' (see ) or 'fhgaacenc.exe' (see ) with it. + Also take care of all neccessary patent and license issues when streaming or broadcasting! + Use the property to decide, whether you want to use the BASS build-in streaming support (default) or if you want to use the BASS.NET internal implementation. + The major difference is, that the BASS.NET implementation allows you to use manually. + + Invalid EncoderType (only MP3 and AAC is supported)! + + Creates a SHOUTcast configuration instance. + + // create an encoder instance + EncoderLAME lame = new EncoderLAME(_recHandle); + lame.LAME_Bitrate = (int)EncoderLAME.BITRATE.kbps_56; + lame.LAME_Mode = EncoderLAME.LAMEMode.Mono; + lame.LAME_TargetSampleRate = (int)EncoderLAME.SAMPLERATE.Hz_22050; + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality; + + // now create the SHOUTcast instance using LAME + SHOUTcast shoutcast = new SHOUTcast(lame); + shoutcast.ServerAddress = "http://serveraddress.com"; + shoutcast.ServerPort = 8000; + shoutcast.Password = "password"; + ... + + + ' create an encoder instance + Dim lame As New EncoderLAME(_recHandle) + lame.LAME_Bitrate = CInt(EncoderLAME.BITRATE.kbps_56) + lame.LAME_Mode = EncoderLAME.LAMEMode.Mono + lame.LAME_TargetSampleRate = CInt(EncoderLAME.SAMPLERATE.Hz_22050) + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality + + ' now create the SHOUTcast instance using LAME + Dim shoutcast As New SHOUTcast(lame) + shoutcast.ServerAddress = "http://serveraddress.com" + shoutcast.ServerPort = 8000 + shoutcast.Password = "password" + ... + + + + + + Creates an instance for a SHOUTcast configuration parameter setting. + + The output encoder instance to be used. + , if BASSenc should be used to handle all cast server handling. , if the internal implementation should be used. + An instance of this class is needed in order to create a instance. + Please note, that you need an appropriate encoder for SHOUTcast streaming. For MP3 streaming we recommend using the latest stable version of LAME (see ). + When streaming in AACplus format an external encoder is needed as well, which accepts pcm data from STDIN and is able to send it's encoded data to STDOUT. + As of today the only 'free' AACplus encoders comes with Winamp - you might use the 'enc_aacPlus.exe' (see ) or 'fhgaacenc.exe' (see ) with it. + Also take care of all neccessary patent and license issues when streaming or broadcasting! + Use the property to decide, whether you want to use the BASS build-in streaming support (default) or if you want to use the BASS.NET internal implementation. + The major difference is, that the BASS.NET implementation allows you to use manually. + + Invalid EncoderType (only MP3 and AAC is supported)! + + Creates a SHOUTcast configuration instance. + + // create an encoder instance + EncoderLAME lame = new EncoderLAME(_recHandle); + lame.LAME_Bitrate = (int)EncoderLAME.BITRATE.kbps_56; + lame.LAME_Mode = EncoderLAME.LAMEMode.Mono; + lame.LAME_TargetSampleRate = (int)EncoderLAME.SAMPLERATE.Hz_22050; + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality; + + // now create the SHOUTcast instance using LAME + SHOUTcast shoutcast = new SHOUTcast(lame, true); + shoutcast.ServerAddress = "http://serveraddress.com"; + shoutcast.ServerPort = 8000; + shoutcast.Password = "password"; + ... + + + ' create an encoder instance + Dim lame As New EncoderLAME(_recHandle) + lame.LAME_Bitrate = CInt(EncoderLAME.BITRATE.kbps_56) + lame.LAME_Mode = EncoderLAME.LAMEMode.Mono + lame.LAME_TargetSampleRate = CInt(EncoderLAME.SAMPLERATE.Hz_22050) + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality + + ' now create the SHOUTcast instance using LAME + Dim shoutcast As New SHOUTcast(lame, True) + shoutcast.ServerAddress = "http://serveraddress.com" + shoutcast.ServerPort = 8000 + shoutcast.Password = "password" + ... + + + + + + SHOUTcast server address (of the form 192.168.1.100 or shoutcast-server.domain.com). + + + + + SHOUTcast server TCP port (usually 8000). + + + + + SHOUTcast v2 SID. + + This property determines if the SHOUTcast v1 or v2 protocol is used! + If this property is set (not an empty string) the SHOUTcast v2 protocol is used - else the SHOUTcast v1 protocol is used! + By default this property is empty (and the SHOUTcast v1 protocol is used). + Note: + The SHOUTcast v2 protocol can ONLY be used, if the property is set to - + else this property is ignored and the SHOUTcast v1 protocol is used! + + + + + Should SHOUTcast v2 metadata updates only use the value? + + Only applies to the SHOUTcast v2 protocol. + Only used with the overload taking a parameter. + If this property is set to only the 'TIT2' metadata tag is send to the server using the current value. + Else (default) the full members are evaluated and the value is ignorred. + + + + + Should in-stream artwork be send to a SHOUTcast v2 server? + + Only applies to the SHOUTcast v2 protocol. Only images up to 511KB will be send. + Only used with the overload taking a parameter. + + + + + Fully qualified path and file name of an alternative artwork picture. + + + Allows you to specify an alternative stream/brand artwork to use, if the playling file doesn't contain one. + Only applies to the SHOUTcast v2 protocol and the property is set to . + Only images up to 511KB will be send. + Only used with the overload taking a parameter. + + + + + Fully qualified path and file name of the station logo picture. + + + Allows you to specify a station logo picture to use. + Only applies to the SHOUTcast v2 protocol and the property is set to . + Only images up to 511KB will be send. + + + + + The next song title ('artist - title') to report within the SHOUTcast v2 metadata. + + + Allows you to specify an 'extension'-'soon' block within the v2 metadata. If empty no 'soon' block (next, upcomming song title) will be reported. Must be specified before a call to . + Only applies to the SHOUTcast v2 protocol. + Note: This property will be cleared after each call and needs to be set again prior to it. + + + + + SHOUTcast server broadcast user name (the "source" username which should be used). + + If empty (default), the default "source" username is used. + + + + SHOUTcast server broadcast password (the "Password" config item on the server's config file). + + + + + A brief description of your station or of what content you'll be broadcasting (usually 10-20 words). + + + + + A genre list of the variety of content you're providing (usually 1-3 words like Rock, 80s, etc.) + + + + + , if you want your broadcast to be listed in the public directory of SHOUTcast broadcasts (default). + Else , which means private. + + + + + A URL of a website that contains information about your broadcast. + + + + + A channel on Efnet IRC for your listeners to interact with (don't worry if you don't understand this). + + + + + If you have one, your ICQ number for listeners to interact with you through. (www.icq.com) + + + + + Your AOL Instant Messenger (AIM) name for listeners to interact with you. (aim.aol.com) + + + + + Establishes a TCP socket connection to the SHOUTcast server. + + on success, else (see or for details). + A server connect will only be successfull, if the underlying was started and is active. + + + + Disconnects from a SHOUTcast server. + + on success, else (see or for details). + Disconnecting from the server will also STOP the underlying encoder by calling the method. + + + + Performs a login and initializes the SHOUTcast server. + + on success, else (see or for details). + If is set to , nothing will happen here and is returned in any case. + So this method is only effective, if is set to . + + + + Sends encoded sample data to the SHOUTcast server (e.g. the data as received in an own ). + + The pointer to the encoded buffer data (as given by to callback). + The length of the buffer data (as given by to callback). + The number of bytes send to the server (or -1, if no bytes could be send (see or for details). + NOTE: Only possible, if is set to . + If an error occures the connection will be closed automatically (using ). + + + + + Updates the song title of the streaming server. + + The new song title to use. + The url which should be updated along with the title (or ). + on success, else (see or for details). + When is set to , will be used internally - + else an internal implementation will be used. + Calling this method also sets the property accordingly. + + + + + Updates the song title of the streaming server. + + The instance to use to set the new song title. + The url which should be updated along with the title (or ). + on success, else (see or for details). + When is set to , will be used internally - + else an internal implementation will be used. + Calling this method does NOT sets the property - but will use it in case of = as the TIT2 metadata value (see )! + If the property is or empty the data will be used instead. + + + + + Updates the station logo picture of the streaming server. + + The fully qualified path and file name of the station logo picture to use. + The property will be updated accordingly and the new station logo will be send to the SHOUTcastv2 server (if connected). + Only applies to the SHOUTcast v2 protocol and the property must be set to . + Only images up to 511KB will be send. + + + + + Returns the number of listeners currently connected. + + The optional admin password to use (=use default). + The current number of listeners (or -1 if not available). + + + + Returns the XML stats of the server. + + The optional admin password to use (=use default). + The string representing the XML formatted statistics (or on error/not available). + + + + Gets or sets, if the SHOUTcast v2 protocol should be used? + + The SHOUTcast v2 protocol is used, if the property is set (not empty) and the property is set to ! + + + + + Returns , if connected and logged into the SHOUTcast server - else . + + + + + ICEcast streaming parameter class. + To be used when creating an instance of the class. + + An instance of the class will providing all necessary setup and configuration data in order to connect to an ICEcast server. + For more information about the ICEcast streaming parameters take a look to the www.icecast.org documentation. + + + + + Creates an instance for an ICEcast configuration parameter setting. + + The output encoder instance to be used. + An instance of this class is needed in order to create a instance. + Please note, that you need an appropriate encoder for ICEcast streaming. For MP3 streaming we recommend using the latest stable version of LAME (see ). For OGG streaming we recommend using the latest stable version of oggenc2 (see ). + When streaming in AACplus format an external encoder is needed as well, which accepts pcm data from STDIN and is able to send it's encoded data to STDOUT. + As of today the only 'free' AACplus encoders comes with Winamp - you might use the 'enc_aacPlus.exe' (see ) or 'fhgaacenc.exe' (see ) with it. + Also take care of all neccessary patent and license issues when streaming or broadcasting! + Use the property to decide, whether you want to use the BASS build-in streaming support (default) or if you want to use the BASS.NET internal implementation. + The major difference is, that the BASS.NET implementation allows you to use manually. + + Invalid EncoderType (only OGG, MP3, AAC or FLAC_OGG is supported)! + + Creates an ICEcast configuration instance. + + // create an encoder instance + EncoderLAME lame = new EncoderLAME(_recHandle); + lame.LAME_Bitrate = (int)EncoderLAME.BITRATE.kbps_56; + lame.LAME_Mode = EncoderLAME.LAMEMode.Mono; + lame.LAME_TargetSampleRate = (int)EncoderLAME.SAMPLERATE.Hz_22050; + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality; + + // now create the ICEcast instance using LAME + ICEcast icecast = new ICEcast(lame); + icecast.ServerAddress = "http://serveraddress.com"; + icecast.ServerPort = 8000; + icecast.Password = "password"; + icecast.Mountpoint = "/mystream"; + ... + + + ' create an encoder instance + Dim lame As New EncoderLAME(_recHandle) + lame.LAME_Bitrate = CInt(EncoderLAME.BITRATE.kbps_56) + lame.LAME_Mode = EncoderLAME.LAMEMode.Mono + lame.LAME_TargetSampleRate = CInt(EncoderLAME.SAMPLERATE.Hz_22050) + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality + + ' now create the ICEcast instance using LAME + Dim icecast As New ICEcast(lame) + icecast.ServerAddress = "http://serveraddress.com" + icecast.ServerPort = 8000 + icecast.Password = "password" + icecast.Mountpoint = "/mystream" + ... + + + + + + Creates an instance for an ICEcast configuration parameter setting. + + The output encoder instance to be used. + , if BASSenc should be used to handle all cast server handling. , if the internal implementation should be used. + An instance of this class is needed in order to create a instance. + Please note, that you need an appropriate encoder for ICEcast streaming. For MP3 streaming we recommend using the latest stable version of LAME (see ). For OGG streaming we recommend using the latest stable version of oggenc2 (see ). + When streaming in AACplus format an external encoder is needed as well, which accepts pcm data from STDIN and is able to send it's encoded data to STDOUT. + As of today the only 'free' AACplus encoders comes with Winamp - you might use the 'enc_aacPlus.exe' (see ) or 'fhgaacenc.exe' (see ) with it. + Also take care of all neccessary patent and license issues when streaming or broadcasting! + Use the property to decide, whether you want to use the BASS build-in streaming support (default) or if you want to use the BASS.NET internal implementation. + The major difference is, that the BASS.NET implementation allows you to use manually. + + Invalid EncoderType (only OGG, MP3 and AAC is supported)! + + Creates an ICEcast configuration instance. + + // create an encoder instance + EncoderLAME lame = new EncoderLAME(_recHandle); + lame.LAME_Bitrate = (int)EncoderLAME.BITRATE.kbps_56; + lame.LAME_Mode = EncoderLAME.LAMEMode.Mono; + lame.LAME_TargetSampleRate = (int)EncoderLAME.SAMPLERATE.Hz_22050; + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality; + + // now create the ICEcast instance using LAME + ICEcast icecast = new ICEcast(lame, true); + icecast.ServerAddress = "http://serveraddress.com"; + icecast.ServerPort = 8000; + icecast.Password = "password"; + icecast.Mountpoint = "/mystream"; + ... + + + ' create an encoder instance + Dim lame As New EncoderLAME(_recHandle) + lame.LAME_Bitrate = CInt(EncoderLAME.BITRATE.kbps_56) + lame.LAME_Mode = EncoderLAME.LAMEMode.Mono + lame.LAME_TargetSampleRate = CInt(EncoderLAME.SAMPLERATE.Hz_22050) + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality + + ' now create the ICEcast instance using LAME + Dim icecast As New ICEcast(lame, True) + icecast.ServerAddress = "http://serveraddress.com" + icecast.ServerPort = 8000 + icecast.Password = "password" + icecast.Mountpoint = "/mystream" + ... + + + + + + ICEcast server address (hostname, in the form 192.168.1.100 or icecast-server.domain.com). + + + + + ICEcast server TCP port (usually 8000). + + + + + The ICEcast mountpoint you want to use. + + All Ogg Vorbis streams should have mountpoints that end in .ogg (i.e. "/mystream.ogg"). + This is due to the lazy way most media players infer the type of stream. + MP3 streams usually do not contain an extension (e.g. "/mystream"). + Mount points also should not contain any spaces or odd characters (again due to the lazy way many of the media players are coded) and MUST start with a slash ('/')! + + + + ICEcast server user name (the "source" username which should be used). + + + + + ICEcast server broadcast password (the "source-password" config item on the server's config file). + + + + + The name of your stream or station (usually 1-5 words). + + + + + A description of your stream or station or of what content you'll be broadcasting (usually 10-20 words). + + + + + A URL of a website that contains information about your broadcast. + + + + + A genre list of the variety of content you're providing (usually 1-3 words like Rock, 80s, etc.) + + + + + , if you want your broadcast to be listed in the public directory of ICEcast broadcasts (default). + Else , which means private. + + + + + The bitrate quality name (e.g. "Quality"). + + Set to (default), if you want to use the effective bitrate (in kbps) of the encoder instead. + + + + Establishes a TCP socket connection to the ICEcast server. + + on success, else (see or for details). + A server connect will only be successfull, if the underlying was started and is active. + + + + Disconnects from an ICEcast server. + + on success, else (see or for details). + Disconnecting from the server will also STOP the underlying encoder by calling the method. + + + + Performs a login and initializes the ICEcast server. + + on success, else (see or for details). + If is set to , nothing will happen here and is returned in any case. + So this method is only effective, if is set to . + + + + Sends encoded sample data to the ICEcast server (e.g. the data as received in an own ). + + The pointer to the encoded buffer data (as given by to callback). + The length of the buffer data (as given by to callback). + The number of bytes send to the server (or -1, if no bytes could be send (see or for details). + NOTE: Only possible, if is set to . + If an error occures the connection will be closed automatically (using ). + + + + + Updates the song title of the streaming server. + + The new song title to use. + - not supported for ICEcast. + on success, else (see or for details). + When is set to , will be used internally - + else an internal implementation will be used. + + + + Updates the artist and title of the streaming server. + + The new artist name to use. + The new title name to use. + on success, else (see or for details). + An internal implementation will be used to set the artist and title. + + + + Returns the number of listeners currently connected. + + The optional admin password to use (=use default). + The current number of listeners (or -1 if not available). + + + + Returns the XML stats of the server. + + The optional admin password to use (=use default). + The string representing the XML formatted statistics (or on error/not available). + + + + Returns , if connected and logged into the ICEcast server - else . + + + + + Windows Media Streaming (WMAcast) streaming parameter class. + To be used when creating an instance of the class. + + An instance of the class will providing all necessary setup and configuration data in order to connect to an Windows Media server or directly stream to the network (acting like a server). + The property will in this implementation in any case return (since BASSwma is used internally). + + + + + Creates an instance for an WMAcast configuration parameter setting. + + The output encoder instance to be used (must be of type ). + An instance of this class is needed in order to create a instance. + Also take care of all neccessary patent and license issues when streaming or broadcasting! + The property will in this implementation in any case be set to (since BASSwma is used internally). + Also the flag will always be forced and set to , as well as the will in any case be set to as well. + + Invalid EncoderType (only OGG, MP3 and AAC is supported)! + Invalid Encoder used, encoder must be of type EncoderWMA! + + Creates an WMAcast configuration instance. + + // create an encoder instance + EncoderWMA wma = new EncoderWMA(_recHandle); + wma.WMA_Bitrate = (int)EncoderWMA.BITRATE.kbps_64; + wma.WMA_UseNetwork = true; + + // now create the WMAcast instance + WMAcast wmacast = new WMAcast(wma); + wmacast.ServerPort = 8080; + ... + wma.Start(null, IntPtr.Zero, true); // start paused + wma.Connect(); + wma.Pause(false); // start encoding + Bass.BASS_ChannelPlay(_recHandle, false); + ... + + + ' create an encoder instance + Dim wma As New EncoderWMA(_recHandle) + wma.WMA_Bitrate = CInt(EncoderWMA.BITRATE.kbps_64) + wma.WMA_UseNetwork = True + + ' now create the WMAcast instance + Dim wmacast As New WMAcast(wma) + wmacast.ServerPort = 8080 + ... + wma.Start(Nothing, IntPtr.Zero, True) ' start paused + wma.Connect() + wma.Pause(False) ' start encoding + Bass.BASS_ChannelPlay(_recHandle, False) + ... + + + + + + An optional author of the stream. + + + + + An optional publisher of the stream. + + + + + An optional genre of the stream. + + + + + A optional copyright notice for the stream. + + + + + A optional description for the stream. + + + + + A optional rating information for the stream. + + + + + A URL of a website that contains information about your broadcast. + + + + + Establishes a connection to the WMAcast server (network or publishing point). + + on success, else (see or for details). + A server connect will only be successfull, if the underlying was started and is active. + + + + Disconnects from an WMAcast server. + + on success, else (see or for details). + + + + Performs a login and initializes the WMAcast server. + + on success, else (see or for details). + + + + Sends sample data to the underlying WMA encoder. + + The pointer to the buffer data. + The length of the buffer data. + The number of bytes send to the server (or -1, if no bytes could be send (see or for details). + + IMPORTANT NOTE: This implementation always return ! + As the underlying automatically sends data to the encoder there is NO need to call this method at all! + This because the will already set up an automatic DSP system whichs feeds the encoder with sample data and already sends the data to the server automatically. + If you want to get notified about any errors when sending data to the encoder you might use the property. + + + + + Updates the song title of the streaming server. + + The new song title to use. + - not supported for WMAcast. + on success, else (see or for details). + Updatig the song title on a Windows Media server does effectivly not work. Use the initial instead. + This method sends the "CAPTION" script command to the encoder. The global is not updated by this call! + This is a text string that is displayed in the captions area of Windows Media Player. + This supports standard HTML formatting, so the text can be formatted as you wish. + + + + + Returns the number of listeners currently connected (only if is set to ). + + The optional admin password to use (=use default). + The current number of listeners (or -1 if not available). + The optional password is actually not used in this implementation. + + + + Returns the XML stats of the server. + + An optional password to use (should be set to to use the default publish password). + The string representing the XML formatted statistics (or on error/not available). + + + + Enables WMA encoding to a publishing point on a Windows Media server (default is , meaning direct network). + + The default mode is active network streaming, meaning this server can directly be used by clients to connect. + Also note, that if streaming to a Windows Media server you must set the properties: , and . + If you set the property to (default), encoding will directly be done to the network (pull mode): users might connect directly to the specified . + Set the property to , in order to enable encoding to a publishing point on a Windows Media server (push mode). + Note: Directly changes the underlying member. + + + + + The network port number for clients to conenct to (only used, if is set to ) - default is 8080. + + + Note: Directly changes the underlying member. + + + + + The maximum number of clients (up to 50) that can be connected (only used, if is set to ) - default is 1. + + + Note: Directly changes the underlying member. + + + + + URL of the publishing point on the Windows Media server (only used, if is set to ). + + + Note: Directly changes the underlying member. + + + + + Username to use in connecting to the server (only used, if is set to ). + + If either this or is , then no username/password is sent to the server. + Note: Directly changes the underlying member. + + + + + Password to use in connecting to the server (only used, if is set to ). + + If either this or is , then no username/password is sent to the server. + Note: Directly changes the underlying member. + + + + + Returns , if connected and logged into the WMAcast server - else . + + + + + Defines a generalized encoder class interface that a class must implement. + + This interface is for example used in the constructor of a streaming server parameter class (e.g. or ) + to specify which encoder settings should be used. + + + + This method must implement the actual start of the encoder. + After the encoder was started successfully the must return a valid HENCODE handle. + + Optional callback function to receive the encoded data... = no callback. + To have the encoded data received by a callback function, the encoder needs to be told to output to STDOUT (instead of a file), so must return true. + User instance data to pass to the callback function. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Should return , if the encoder was successfully started - else must be returned. + An imlementation of this method should internally call accordingly using the . + After the encoder was started successfully the must return a valid HENCODE handle. + If the encoder was not started successfully or was stopped must return 0 (zero). + + + + This method must implement the actual stop of the encoder. + After the encoder was stopped successfully the must return 0 (zero). + + Should return , if the encoder was successfully stopped - else must be returned and an must stay as before. + An imlementation of this method should internally call accordingly using the . + After the encoder was stopped successfully the must return 0 (zero). + If the encoder was not stopped and is still active or simply paused must return a valid HENCODE (non-zero). + + + + This method must implement the actual pauseing of the encoder. + After the encoder was paused successfully the must still return a valid HENCODE handle (non-zero). + + Pause the encoder () or unpause (). + Should return , if the encoder was successfully paused - else must be returned and an must stay as before. + An imlementation of this method should internally call accordingly using the . + After the encoder was paused successfully the must still return a valid HENCODE handle (non-zero). + If the encoder was not started successfully or was stopped must return 0 (zero). + + + + This property should get or sets the channel handle which will be used to create the broadcast encoder class. + + Only set this member to a new channel, if the encoder is not active (otherwise the channel will not be changed)! + + + + This property should return the actual bitwidth of the sample data BASS is using with the channel (e.g. 8, 16, 32). + + BASS supports 8/16/32-bit sample data, so if a WAV file, for example, uses another sample resolution, it'll have to be converted by BASS. + This bitwidth represents the bitwidth which is used by BASS (e.g. in a DSP callback delegate) and does not represent the original bitwidth of the stream. + The bitwidth used by BASS is determined how the underlying channel handle was created (e.g. using with the or flag) + and if the option has been set. + If non of the above was used, by default 16 bits per sample are used. + + + + + This property should return the actual sample rate in Hz of the sample data BASS is using with the channel (e.g. 44100). + + + + + This property should return the actual number of channles of the sample data BASS is using with the channel (e.g. 1=mono, 2=stereo, etc.). + + BASS supports multi-channel sample data, so make sure the actual encoder implementation supports multi-channel too. + If the encoder does not support multi-channel make sure that you are using non-multi-channel hanles only. + + + + + This property should return a value indicating which type of content the broadcast encoder implements. + + For example: If the implementation of the broadcast encoder implements an MP3 encoder, you should return BASS_CTYPE_STREAM_MP3. + For a complete list see . + + + + This property should return the default extension of an output file for this encoder (e.g. ".mp3" or ".ogg" etc.). + + + + + This property should return , if the base encoder implementation (resp. the underlying command-line tool being used) support STDOUT for output of the encoded data - else must be returned. + + In order to support broadcast streaming with an encoder command-line tool, + the encoded data needs to be received back by a callback function, so the encoder needs to be told to output to STDOUT (instead of a file). + + + + This property should get and set a HENCODE encoder handle as returned by the method if the the encoder has been started (see ) or 0 (zero), if the encoder has not been started or was stopped (see ). + + Take note of the member, which might need to use the the encoder handle in order to retrieve the encoder state. + If the encoder is not started or not started successfully (see ) or is stopped this property must return 0 (zero)! + If the encoder is started and is active this property must return the valid HENCODE handle (non-zero)! + + + + + This property should return , if the encoder has been started (see ) and is active - else must be returned. + + An implementation should first get the . + If the encoder handle is valid (non-zero) the implementation might use the method in order to check it's state. + If the state is not BASS_ACTIVE_STOPPED this property should return . + In all other cases this property should return (not started, paused, stopped etc.) + + + + This property should return , only if the encoder has been paused (see ) - else must be returned. + + An implementation should first get the . + If the encoder handle is valid (non-zero) the implementation might use the method in order to check it's state. + Only if the state is BASS_ACTIVE_PAUSED this property should return . + In all other cases this property should return (not started, active, playing etc.) + + + + This property should return an encoder command-line string, + which might be used with the method in order to create and start the encoder. + + Make sure, that the encoder command-line is evaluating the and members correctly. + + + + This property should get and set the encoder's base directory. + It might be used in the implementation to return a fully qualified encoder command-line. + + + + + This property should return , if the encoder exists and is available - else should be returned. + + When using a command-line encoder this method might check, if the executable file exists in the specified . + + + + Specifies the input file name to be processed by the encoder (null = STDIN). + + This member should be used when implementing the property. + + + + Gets or Sets if a encoding in 16-bit sample data should be forced (default is ). + + This member should be used when implementing the property. + When you want to encode a floating-point channel, but the encoder does not support 32-bit floating-point sample data, then you can use this flags to have the sample data converted to 16 bit integer data before it's passed on to the encoder. + + + + + Gets or Sets if encoding should use the CAST_NOLIMIT flag (which is only needed, if the encoder is used for streaming). + + With this option you might disable the rate limiting during casting (as it'll be limited by the playback rate anyway if the source channel is being played). + + + + Gets or Sets if encoding should use an async queue (i.e. the BASS_ENCODE_QUEUE flag). + + + With this option you might enable queueing of sample data and feeding it to the encoder asynchronously in another thread, + so that any update thread isn't delayed by the encoding. + This might be usefull when encoding a playback stream or a recording stream which is feeding playback. + + + + + Specifies the output file name to be processed by the encoder (null = STDOUT). + + This member should be used when implementing the property. + + + + Specifies the target effective bitrate of the encoder output (in kbps, e.g. 128 kbps). + + This member must return a valid bitrate, if you are using the encoder in a implementation. + If you are encoding in VBR or ABR this member must also return a valid bitrate (e.g. approximated). + You might use one of the constants in order to set a valid effective bitrate. + + + + Gets or Sets the structure associated with the encoder. + + By default this member is - meaning no Tag info is used with the encoder. + If you set this property to a valid instance before you call , this will be used (when supported by the encoder) to automatically write the respective tag info to the output. + Meaning the will be modified accordingly. + The TAGs will only be used, if you have specified an . + + + + + Base class for all encoder implementation classes (e.g. , or ). + + This base class is not intended for direct use, but defines all abstract properties and methods which needs to be implemented by an actual broadcast encoder class. + Internally, the sending of sample data to the encoder is implemented via a DSP callback on the . That means when you play the (or call if it's a decoding channel), the sample data will be sent to the encoder at the same time. + It also means that if the BASS_CONFIG_FLOATDSP option is enabled, the sample data will be 32-bit floating-point. + A derived class must implement: , , , and . + The properties , , , , , , , , and + as well as the methods and have been already implemented. + You might use this base class to derive your own Encoder implementations. + In this case a derived class must only implement the following members: , , and . + If an instance of a derived class is being disposed, an already assigned Encoder will automatically be stopped. + How to use an encoder implementation: + + Scenario:How-To: + "Recording" To "Streaming": + Create a recording handle with . + Set and to (STDIN, STDOUT). + Use the encoder instance to create a , which is then used by the class. + + "Recording" To "File": + Create a recording handle with . + Set to and the to a file name (STDIN, file). + Call to start encoding and to stop the live recording encoding. + + EncoderNeroAAC n = new EncoderNeroAAC(_recHandle); + n.InputFile = null; + n.OutputFile = "test.m4a"; + n.NERO_Bitrate = 48; + n.Start(null, IntPtr.Zero, false); + // your recording will be encoded until you call... + n.Stop(); + + + Dim n As New EncoderNeroAAC(_recHandle) + n.InputFile = Nothing + n.OutputFile = "test.m4a" + n.NERO_Bitrate = 48 + n.Start(Nothing, IntPtr.Zero, False) + ' your recording will be encoded until you call... + n.Stop() + + + "Stream" To "Streaming": + Create a stream handle e.g. with (either normal or decoding). + Set to and the to a file name (STDIN, file). + Use the encoder instance to create a , which is then used by the class. + Call resp. (if using a decoding stream) to play resp. decode the stream and actually feed the encoder and therewith the broadcasting server. + Hint: You might use to create a continues mixer output stream channel for streaming. + + "Stream" To "File": + Create a stream handle e.g. with (either normal or decoding). + Set to and the to a file name (STDIN, file). + Call resp. (if using a decoding stream) to play resp. decode the stream and actually feed the encoder. + + int stream = Bass.BASS_StreamCreateFile("test.wav", 0, 0, BASSFlag.BASS_STREAM_DECODE); + EncoderLAME l = new EncoderLAME(stream); + l.InputFile = null; //STDIN + l.OutputFile = "test.mp3"; + l.LAME_Bitrate = (int)EncoderLAME.BITRATE.kbps_64; + l.LAME_Mode = EncoderLAME.LAMEMode.Default; + l.LAME_Quality = EncoderLAME.LAMEQuality.Quality; + l.Start(null, IntPtr.Zero, false); + // decode the stream (if not using a decoding channel, simply call "Bass.BASS_ChannelPlay" here) + byte[] encBuffer = new byte[65536]; // our dummy encoder buffer + while (Bass.BASS_ChannelIsActive(stream) == BASSActive.BASS_ACTIVE_PLAYING) + { + // getting sample data will automatically feed the encoder + int len = Bass.BASS_ChannelGetData(_stream, encBuffer, encBuffer.Length); + } + l.Stop(); // finish + Bass.BASS_StreamFree(stream); + + + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.wav", 0, 0, BASSFlag.BASS_STREAM_DECODE) + Dim l As New EncoderLAME(stream) + l.InputFile = Nothing 'STDIN + l.OutputFile = "test.mp3" + l.LAME_Bitrate = CInt(EncoderLAME.BITRATE.kbps_64) + l.LAME_Mode = EncoderLAME.LAMEMode.Default + l.LAME_Quality = EncoderLAME.LAMEQuality.Quality + l.Start(Nothing, IntPtr.Zero, False) + ' decode the stream (if not using a decoding channel, simply call "Bass.BASS_ChannelPlay" here) + Dim encBuffer(65536) As Byte ' our dummy encoder buffer + While Bass.BASS_ChannelIsActive(stream) = BASSActive.BASS_ACTIVE_PLAYING + ' getting sample data will automatically feed the encoder + Dim len As Integer = Bass.BASS_ChannelGetData(_stream, encBuffer, encBuffer.Length) + End While + l.Stop() ' finish + Bass.BASS_StreamFree(stream) + + + "File" To "Streaming": + Create a stream handle e.g. with (either normal or decoding). + Just like the above example. And use the stream handle to create the encoder instance. + Set to and to (STDIN, STDOUT). + Use the encoder instance to create a , which is then used by the class. + + "File" To "File": + No stream handle is actually needed. + Set and to a file name (file, file). + Call to start encoding and to stop encoding. + Or simply use the method instead. + + EncoderOGG o = new EncoderOGG(0); + o.InputFile = "test.wav"; + o.OutputFile = "test.ogg"; + o.OGG_UseQualityMode = true; + o.OGG_Quality = 4; + BaseEncoder.EncodeFile(o, null, true, false, true); + + + Dim o As New EncoderOGG(0) + o.InputFile = "test.wav" + o.OutputFile = "test.ogg" + o.OGG_UseQualityMode = True + o.OGG_Quality = 4 + BaseEncoder.EncodeFile(o, Nothing, True, False, True) + + + + + + + This example shows a basic implementation of an own Encoder class: + + public class MyOwnEncoder : BaseEncoder + { + // Constructor + public MyOwnEncoder(int channel) : base(channel) + { + } + + public override string ToString() + { + return "My Encoder (BASS_CTYPE_STREAM_MP3)"; + } + + public override string DefaultOutputExtension + { + get { return ".mp3"; } + } + + public override BASSChannelType EncoderType + { + get { return BASSChannelType.BASS_CTYPE_STREAM_MP3; } + } + + public override bool SupportsSTDOUT + { + get { return true; } + } + + public override string EncoderCommandLine + { + get { return BuildEncoderCommandLine(); } + } + + public override int EffectiveBitrate + { + get { return My_Bitrate; } + } + + public override bool Start(ENCODEPROC proc, IntPtr user, bool paused) + { + if (EncoderHandle != 0 || (proc != null && !SupportsSTDOUT)) + return false; + // start the encoder + BASSEncode flag = BASSEncode.BASS_ENCODE_NOHEAD; + if (Force16Bit) + flag |= BASSEncode.BASS_ENCODE_FP_16BIT; + if (paused) + flag |= BASSEncode.BASS_ENCODE_PAUSE; + EncoderHandle = BassEnc.BASS_Encode_Start(ChannelHandle, EncoderCommandLine, + flag, proc, user); + if (EncoderHandle == 0) + return false; + else + return true; + } + + // local members for setting individual parameters + public int My_Bitrate = 128; + + // just an example here! + private string BuildEncoderCommandLine() + { + CultureInfo enCI = new CultureInfo("en-US", false); + StringBuilder sb = new StringBuilder(); + // the file name and path + sb.Append( Path.Combine( EncoderDirectory, "myencoder.exe" ) ); + // raw input? + if (InputFile == null) // STDIN: add the raw pcm header data + sb.Append( String.Format( enCI, " -r -x -s {0:##0.0##} --bitwidth {1}", + ChannelSampleRate/1000f, ChannelBitwidth > 16 ? 16 : ChannelBitwidth ) ); + // ...more options here... + sb.Append( String.Format( enCI, " -b {0} -h", My_Bitrate ) ); + // STDIN or filename + if (InputFile != null) + sb.Append( " \""+InputFile+"\"" ); + else + sb.Append( " -" ); + // STDOUT or filename + if (OutputFile != null) + sb.Append( " \""+OutputFile+"\"" ); + else + sb.Append( " -" ); + return sb.ToString(); + } + } + + + Public Class MyOwnEncoder Inherits BaseEncoder + + ' Constructor + Public Sub New(channel As Integer) MyBase.New(channel) + End Sub + + Public Overrides Function ToString() As String + Return "My Encoder (BASS_CTYPE_STREAM_MP3)" + End Function + + Public Overrides ReadOnly Property DefaultOutputExtension() As String + Get + Return ".mp3" + End Get + End Property + + Public Overrides ReadOnly Property EncoderType() As BASSChannelType + Get + Return BASSChannelType.BASS_CTYPE_STREAM_MP3 + End Get + End Property + + Public Overrides ReadOnly Property SupportsSTDOUT() As Boolean + Get + Return True + End Get + End Property + + Public Overrides ReadOnly Property EncoderCommandLine() As String + Get + Return BuildEncoderCommandLine() + End Get + End Property + + Public Overrides ReadOnly Property EffectiveBitrate() As Integer + Get + Return My_Bitrate + End Get + End Property + + Public Overrides Function Start(proc As ENCODEPROC, user As IntPtr, paused As Boolean) As Boolean + If EncoderHandle <> 0 OrElse (Not (proc Is Nothing) AndAlso Not SupportsSTDOUT) Then + Return False + End If + ' start the encoder + Dim flag As BASSEncode = BASSEncode.BASS_ENCODE_NOHEAD + If Force16Bit Then + flag = flag Or BASSEncode.BASS_ENCODE_FP_16BIT + End If + If paused Then + flag = flag Or BASSEncode.BASS_ENCODE_PAUSE + End If + EncoderHandle = BassEnc.BASS_Encode_Start(ChannelHandle, EncoderCommandLine, + flag, proc, user) + End If + If EncoderHandle = 0 Then + Return False + Else + Return True + End If + End Function + + ' local members for setting individual parameters + Public My_Bitrate As Integer = 128 + + ' just an example here! + Private Function BuildEncoderCommandLine() As String + Dim enCI As New CultureInfo("en-US", False) + Dim sb As New StringBuilder() + ' the file name and path + sb.Append(Path.Combine(EncoderDirectory, "myencoder.exe")) + ' raw input? + If InputFile Is Nothing Then ' STDIN: add the raw pcm header data + sb.Append([String].Format(enCI, " -r -x -s {0:##0.0##} --bitwidth {1}", + ChannelSampleRate / 1000F,(If ChannelBitwidth > 16 Then 16 Else ChannelBitwidth))) 'ToDo: Unsupported feature: conditional (?) operator. + End If ' ...more options here... + sb.Append([String].Format(enCI, " -b {0} -h", My_Bitrate)) + ' STDIN or filename + If Not (InputFile Is Nothing) Then + sb.Append((" """ + InputFile + """")) + Else + sb.Append(" -") + End If ' STDOUT or filename + If Not (OutputFile Is Nothing) Then + sb.Append((" """ + OutputFile + """")) + Else + sb.Append(" -") + End If + Return sb.ToString() + End Function + + End Class + + + + + + Default constructor, which already evaluates the channel handle and evaluates the . + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + If you pass 0 (zero) as a channel handle, all members are initialized with some default values. + You can change the channel handle by assigning a new value to the property. + A channel handle can only be changed, if the encoder is not active (see ). + + + + + Implement IDisposable. + + Do not make this method virtual. A derived class should not be able to override this method. + + + + Finalization code. + + This destructor will run only if the Dispose method does not get called. + It gives your base class the opportunity to finalize. Do not provide destructors in types derived from this class. + + + + This method must implement the actual start of the encoder. + After the encoder was started successfully the must return a valid HENCODE handle. + + Optional callback function to receive the encoded data... = no callback. + To have the encoded data received by a callback function, the encoder needs to be told to output to STDOUT (instead of a file), so must return true. + User instance data to pass to the callback function. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Should return , if the encoder was successfully started - else must be returned. + An imlementation of this method should internally call accordingly using the . + After the encoder was started successfully the must return a valid HENCODE handle. + If the encoder was not started successfully or was stopped must return 0 (zero). + + + + Stops the encoder (if started). + + Returns , if the encoder was successfully stopped - else is returned. + Internally is called using the . + After the encoder was stopped successfully the is set to 0 (zero). + If the encoder was not stopped the is left unchanged. + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Stops the encoder (if started). + + to tell BASSenc to wait for the async queue to be processed (the function will still return immediately but the encoder won't be freed yet). + Returns , if the encoder was successfully stopped - else is returned. + This overload is only in effect, if is set (to ). + Internally is called using the . + After the encoder was stopped successfully the is set to 0 (zero). + If the encoder was not stopped the is left unchanged. + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Pauses or resumes an encoder. + + = pause the encoder, = resume the encoder. + Returns , if the encoder was successfully paused/resumed - else must be returned and an must stay as before. + + After the encoder was paused/resumed successfully the must still return a valid HENCODE handle (non-zero). + The default imlementation of this method calls accordingly using the . + So normally there is no need to override this method. + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Encodes a given input file to a given output file using the specified encoder. + + The input filename to encode (must exist). + The target output filename (if , the filename will be composed by changing the file extension to the ). + The encoder to be used (make sure you set all the parameter members of the encoder before). + An optional callback procedure which should be called during the encoding process in order to inform you about the encoding progress ( = no notifcation). + Set to , if you want to force to overwrite any already existing output file (will delete the existing file). If set to and the output file already exists the method will fail, but the existing file will not be deleted. + Set to , if you want to delete the input file after the encoding has been successfully completed. + Returns , if the input file was successfully encoded. Returns if any error occured. + The method will use in order to open the input file for encoding. 16-bit will always be used here to read the inputFile. + So any file format supported by BASS or the BASS plugin system might be used. + + The output file already exists (only raised when the is not used). + + Encodes a file using the EncoderWMA (CBR at 128 kbps): + + EncoderWMA wma = new EncoderWMA(0); + wma.WMA_Bitrate = 128; + BaseEncoder.EncodeFile("test.wav", null, wma, + new BaseEncoder.ENCODEFILEPROC(FileEncodingNotification), true, false); + + public void FileEncodingNotification(long bytesTotal, long bytesDone) + { + Console.Write("Encoding: {0:P}\r", Math.Round((double)bytesDone/(double)bytesTotal, 2)); + } + + + Dim wma As New EncoderWMA(0) + wma.WMA_Bitrate = 128 + BaseEncoder.EncodeFile("test.wav", Nothing, wma, + New BaseEncoder.ENCODEFILEPROC(FileEncodingNotification), True, False) + + Public Sub FileEncodingNotification(bytesTotal As Long, bytesDone As Long) + Console.Write("Encoding: {0:P}\r", Math.Round(CDbl(bytesDone) / CDbl(bytesTotal), 2)) + End Sub + + Encodes OGG input to an MP3 output using EncoderLAME (with the 'standard' preset): + + EncoderLAME enc = new EncoderLAME(0); + enc.LAME_PresetName = "standard"; + BaseEncoder.EncodeFile("test.ogg", null, enc, null, true, false); + + + Dim enc As New EncoderLAME(0) + enc.LAME_PresetName = "standard" + BaseEncoder.EncodeFile("test.ogg", Nothing, enc, Nothing, True, False) + + + + + + Encodes a given input file to a given output file using the specified encoder. + + The encoder to be used (make sure you set all the parameter members of the encoder before). + An optional callback procedure which should be called during the encoding process in order to inform you about the encoding progress ( = no notifcation). + Set to , if you want to force to overwrite any already existing output file (will delete the existing file). If set to and the output file already exists the method will fail, but the existing file will not be deleted. + Set to , if you want to delete the input file after the encoding has been successfully completed. + Returns , if the input file was successfully encoded. Returns if any error occured. + The InputFile and OutputFile will be taken from the encoder settings! + The method will use in order to open the input file for encoding. 16-bit will always be used here to read the inputFile. + So any file format supported by BASS or the BASS plugin system might be used. + + The output file already exists (only raised when the is not used). + + Encodes a file using the EncoderWMA (using CBR at 128 kbps Pro): + + EncoderWMA wma = new EncoderWMA(0); + wma.InputFile = "testin.ogg"; + wma.OutputFile = "testout.wma"; + wma.WMA_Bitrate = 128; + wma.WMA_UsePro = true; + BaseEncoder.EncodeFile(wma, new BaseEncoder.ENCODEFILEPROC(FileEncodingNotification), true, false); + + public void FileEncodingNotification(long bytesTotal, long bytesDone) + { + Console.Write("Encoding: {0:P}\r", Math.Round((double)bytesDone/(double)bytesTotal, 2)); + } + + + Dim wma As New EncoderWMA(0) + wma.InputFile = "testin.ogg" + wma.OutputFile = "testout.wma" + wma.WMA_Bitrate = 128 + wma.WMA_UsePro = True + BaseEncoder.EncodeFile(wma, New BaseEncoder.ENCODEFILEPROC(FileEncodingNotification), True, False) + + Public Sub FileEncodingNotification(bytesTotal As Long, bytesDone As Long) + Console.Write("Encoding: {0:P}\r", Math.Round(CDbl(bytesDone) / CDbl(bytesTotal), 2)) + End Sub + + + + + + Encodes a given input file to a given output file using the specified encoder. + + The input filename to encode (must exist). + The target output filename (if , the filename will be composed by changing the file extension to the ). + The encoder to be used (make sure you set all the parameter members of the encoder before). + An optional callback procedure which should be called during the encoding process in order to inform you about the encoding progress ( = no notifcation). + Set to , if you want to force to overwrite any already existing output file (will delete the existing file). If set to and the output file already exists the method will fail, but the existing file will not be deleted. + Set to , if you want to delete the input file after the encoding has been successfully completed. + Set to , if you want to use the TAGs from the input file and write them also to the output file. will write the output without any TAGs. + Returns , if the input file was successfully encoded. Returns if any error occured. + The method will use in order to open the input file for encoding. 16-bit will always be used here to read the inputFile. + So any file format supported by BASS or the BASS plugin system might be used. + + The output file already exists (only raised when the is not used). + + Re-Encodes an OGG file to MP3 using the EncoderLAME (no notification, but copying the TAGs): + + EncoderLAME lame = new EncoderLAME(0); + lame.LAME_Bitrate = (int)EncoderLAME.BITRATE.kbps_192; + lame.LAME_Mode = EncoderLAME.LAMEMode.Default; + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality; + lame.TAGs = BassTags.BASS_TAG_GetFromFile("testin.ogg", true, false);; + BaseEncoder.EncodeFile("testin.ogg", "testout.mp3", lame, null, true, false, true); + + + Dim lame As New EncoderLAME(0) + lame.LAME_Bitrate = CInt(EncoderLAME.BITRATE.kbps_192) + lame.LAME_Mode = EncoderLAME.LAMEMode.Default + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality + lame.TAGs = BassTags.BASS_TAG_GetFromFile("testin.ogg", True, False) + BaseEncoder.EncodeFile("testin.ogg", "testout.mp3", lame, Nothing, True, False, True) + + + + + + Encodes a given input file to a given output file using the specified encoder. + + The encoder to be used (make sure you set all the parameter members of the encoder before). + An optional callback procedure which should be called during the encoding process in order to inform you about the encoding progress ( = no notifcation). + Set to , if you want to force to overwrite any already existing output file (will delete the existing file). If set to and the output file already exists the method will fail, but the existing file will not be deleted. + Set to , if you want to delete the input file after the encoding has been successfully completed. + Set to , if you want to use the TAGs from the input file and write them also to the output file. will write the output without any TAGs. + Returns , if the input file was successfully encoded. Returns if any error occured. + The InputFile and OutputFile will be taken from the encoder settings! + The method will use in order to open the input file for encoding. 16-bit will always be used here to read the inputFile. + So any file format supported by BASS or the BASS plugin system might be used. + + The output file already exists (only raised when the is not used). + + Re-Encodes an OGG file to MP3 using the EncoderLAME (manual tagging): + + TAG_INFO tags = new TAG_INFO(); + tags.artist = "The Artist"; + tags.title = "The Title"; + + EncoderLAME lame = new EncoderLAME(0); + lame.InputFile = "test.ogg"; + lame.TAGs = tags; + lame.LAME_Bitrate = (int)EncoderLAME.BITRATE.kbps_192; + lame.LAME_Mode = EncoderLAME.LAMEMode.Default; + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality; + BaseEncoder.EncodeFile(lame, + new BaseEncoder.ENCODEFILEPROC(FileEncodingNotification), true, false, true); + + public void FileEncodingNotification(long bytesTotal, long bytesDone) + { + Console.Write("Encoding: {0:P}\r", Math.Round((double)bytesDone/(double)bytesTotal, 2)); + } + + + Dim tags As New TAG_INFO() + tags.artist = "The Artist" + tags.title = "The Title" + + Dim lame As New EncoderLAME(0) + lame.InputFile = "test.ogg" + lame.TAGs = tags + lame.LAME_Bitrate = CInt(EncoderLAME.BITRATE.kbps_192) + lame.LAME_Mode = EncoderLAME.LAMEMode.Default + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality + BaseEncoder.EncodeFile(lame, + New BaseEncoder.ENCODEFILEPROC(FileEncodingNotification), True, False, True) + + Public Sub FileEncodingNotification(bytesTotal As Long, bytesDone As Long) + Console.Write("Encoding: {0:P}\r", Math.Round(CDbl(bytesDone) / CDbl(bytesTotal), 2)) + End Sub + + + + + + Encodes a given input file to a given output file using the specified encoder. + + The input filename to encode (must exist). + The target output filename (if , the filename will be composed by changing the file extension to the ). + The encoder to be used (make sure you set all the parameter members of the encoder before). + An optional callback procedure which should be called during the encoding process in order to inform you about the encoding progress ( = no notifcation). + Set to , if you want to force to overwrite any already existing output file (will delete the existing file). If set to and the output file already exists the method will fail, but the existing file will not be deleted. + Set to , if you want to delete the input file after the encoding has been successfully completed. + Set to , if you want to use the TAGs from the input file and write them also to the output file. will write the output without any TAGs. + Sets the start position in bytes from where to start encoding or -1 to encode from the beginning. + Sets the end position in bytes til where want to encode or -1 to encode til the end. toPos must be greater than fromPos! + Returns , if the input file was successfully encoded. Returns if any error occured. + The method will use in order to open the input file for encoding. 16-bit will always be used here to read the inputFile. + So any file format supported by BASS or the BASS plugin system might be used. + + The output file already exists (only raised when the is not used). + + Re-Encodes an OGG file partially to MP3 using the EncoderLAME: + + EncoderLAME lame = new EncoderLAME(0); + lame.LAME_Bitrate = (int)EncoderLAME.BITRATE.kbps_192; + lame.LAME_Mode = EncoderLAME.LAMEMode.Default; + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality; + BaseEncoder.EncodeFile("testin.ogg", "testout.mp3", lame, null, true, false, true, 4096, 61440); + + + Dim lame As New EncoderLAME(0) + lame.LAME_Bitrate = CInt(EncoderLAME.BITRATE.kbps_192) + lame.LAME_Mode = EncoderLAME.LAMEMode.Default + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality + BaseEncoder.EncodeFile("testin.ogg", "testout.mp3", lame, Nothing, True, False, True, 4096, 61440) + + + + + + Encodes a given input file to a given output file using the specified encoder. + + The encoder to be used (make sure you set all the parameter members of the encoder before). + An optional callback procedure which should be called during the encoding process in order to inform you about the encoding progress ( = no notifcation). + Set to , if you want to force to overwrite any already existing output file (will delete the existing file). If set to and the output file already exists the method will fail, but the existing file will not be deleted. + Set to , if you want to delete the input file after the encoding has been successfully completed. + Set to , if you want to use the TAGs from the input file and write them also to the output file. will write the output without any TAGs. + Sets the start position in bytes from where to start encoding or -1 to encode from the beginning. + Sets the end position in bytes til where want to encode or -1 to encode til the end. toPos must be greater than fromPos! + Returns , if the input file was successfully encoded. Returns if any error occured. + The InputFile and OutputFile will be taken from the encoder settings! + The method will use in order to open the input file for encoding. 16-bit will always be used here to read the inputFile. + So any file format supported by BASS or the BASS plugin system might be used. + + The output file already exists (only raised when the is not used). + + Re-Encodes an OGG file partially to MP3 using the EncoderLAME: + + EncoderLAME lame = new EncoderLAME(0); + lame.InputFile = "testin.ogg"; + lame.OutputFile = "testout.mp3"; + lame.LAME_Bitrate = (int)EncoderLAME.BITRATE.kbps_192; + lame.LAME_Mode = EncoderLAME.LAMEMode.Default; + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality; + BaseEncoder.EncodeFile(lame, + new BaseEncoder.ENCODEFILEPROC(FileEncodingNotification), + true, false, true, 4096, 61440); + + public void FileEncodingNotification(long bytesTotal, long bytesDone) + { + Console.Write("Encoding: {0:P}\r", Math.Round((double)bytesDone/(double)bytesTotal, 2)); + } + + + Dim lame As New EncoderLAME(0) + lame.InputFile = "testin.ogg" + lame.OutputFile = "testout.mp3" + lame.LAME_Bitrate = CInt(EncoderLAME.BITRATE.kbps_192) + lame.LAME_Mode = EncoderLAME.LAMEMode.Default + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality + BaseEncoder.EncodeFile(lame, + New BaseEncoder.ENCODEFILEPROC(FileEncodingNotification), + True, False, True, 4096, 61440) + + Public Sub FileEncodingNotification(bytesTotal As Long, bytesDone As Long) + Console.Write("Encoding: {0:P}\r", Math.Round(CDbl(bytesDone) / CDbl(bytesTotal), 2)) + End Sub + + + + + + Encodes a given input file to a given output file using the specified encoder. + + The input filename to encode (must exist). + The target output filename (if , the filename will be composed by changing the file extension to the ). + The encoder to be used (make sure you set all the parameter members of the encoder before). + An optional callback procedure which should be called during the encoding process in order to inform you about the encoding progress ( = no notifcation). + Set to , if you want to force to overwrite any already existing output file (will delete the existing file). If set to and the output file already exists the method will fail, but the existing file will not be deleted. + Set to , if you want to delete the input file after the encoding has been successfully completed. + Set to , if you want to use the TAGs from the input file and write them also to the output file. will write the output without any TAGs. + Sets the start position in seconds (incl. fractions) from where to start encoding or -1.0f to encode from the beginning. + Sets the end position in seconds (incl. fractions) til where want to encode or -1.0f to encode til the end. toPos must be greater than fromPos! + Returns , if the input file was successfully encoded. Returns if any error occured. + The method will use in order to open the input file for encoding. 16-bit will always be used here to read the inputFile. + So any file format supported by BASS or the BASS plugin system might be used. + + The output file already exists (only raised when the is not used). + + Re-Encodes an OGG file partially to MP3 using the EncoderLAME: + + EncoderLAME lame = new EncoderLAME(0); + lame.LAME_Bitrate = (int)EncoderLAME.BITRATE.kbps_192; + lame.LAME_Mode = EncoderLAME.LAMEMode.Default; + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality; + BaseEncoder.EncodeFile("testin.ogg", "testout.mp3", lame, + new BaseEncoder.ENCODEFILEPROC(FileEncodingNotification), + true, false, true, 5.1f, 25.3f); + + public void FileEncodingNotification(long bytesTotal, long bytesDone) + { + Console.Write("Encoding: {0:P}\r", Math.Round((double)bytesDone/(double)bytesTotal, 2)); + } + + + Dim lame As New EncoderLAME(0) + lame.LAME_Bitrate = CInt(EncoderLAME.BITRATE.kbps_192) + lame.LAME_Mode = EncoderLAME.LAMEMode.Default + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality + BaseEncoder.EncodeFile("testin.ogg", "testout.mp3", lame, + New BaseEncoder.ENCODEFILEPROC(FileEncodingNotification), + True, False, True, 5.1F, 25.3F) + + Public Sub FileEncodingNotification(bytesTotal As Long, bytesDone As Long) + Console.Write("Encoding: {0:P}\r", Math.Round(CDbl(bytesDone) / CDbl(bytesTotal), 2)) + End Sub + + + + + + Encodes a given input file to a given output file using the specified encoder. + + The encoder to be used (make sure you set all the parameter members of the encoder before). + An optional callback procedure which should be called during the encoding process in order to inform you about the encoding progress ( = no notifcation). + Set to , if you want to force to overwrite any already existing output file (will delete the existing file). If set to and the output file already exists the method will fail, but the existing file will not be deleted. + Set to , if you want to delete the input file after the encoding has been successfully completed. + Set to , if you want to use the TAGs from the input file and write them also to the output file. will write the output without any TAGs. + Sets the start position in seconds (incl. fractions) from where to start encoding or -1.0f to encode from the beginning. + Sets the end position in seconds (incl. fractions) til where want to encode or -1.0f to encode til the end. toPos must be greater than fromPos! + Returns , if the input file was successfully encoded. Returns if any error occured. + The InputFile and OutputFile will be taken from the encoder settings! + The method will use in order to open the input file for encoding. 16-bit will always be used here to read the inputFile. + So any file format supported by BASS or the BASS plugin system might be used. + + The output file already exists (only raised when the is not used). + + Re-Encodes an OGG file to MP3 using the EncoderLAME partially: + + EncoderLAME lame = new EncoderLAME(0); + lame.InputFile = "testin.ogg"; + lame.OutputFile = "testout.mp3"; + lame.LAME_Bitrate = (int)EncoderLAME.BITRATE.kbps_192; + lame.LAME_Mode = EncoderLAME.LAMEMode.Default; + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality; + BaseEncoder.EncodeFile(lame, + new BaseEncoder.ENCODEFILEPROC(FileEncodingNotification), + true, false, true, + 5.1f, 25.3f); + + public void FileEncodingNotification(long bytesTotal, long bytesDone) + { + Console.Write("Encoding: {0:P}\r", Math.Round((double)bytesDone/(double)bytesTotal, 2)); + } + + + Dim lame As New EncoderLAME(0) + lame.InputFile = "testin.ogg" + lame.OutputFile = "testout.mp3" + lame.LAME_Bitrate = CInt(EncoderLAME.BITRATE.kbps_192) + lame.LAME_Mode = EncoderLAME.LAMEMode.Default + lame.LAME_Quality = EncoderLAME.LAMEQuality.Quality + BaseEncoder.EncodeFile(lame, + New BaseEncoder.ENCODEFILEPROC(FileEncodingNotification), + True, False, True, 5.1F, 25.3F) + + Public Sub FileEncodingNotification(bytesTotal As Long, bytesDone As Long) + Console.Write("Encoding: {0:P}\r", Math.Round(CDbl(bytesDone) / CDbl(bytesTotal), 2)) + End Sub + + + + + + Gets or Sets the channel handle which is used to create the broadcast encoder class. + + This allows you to move the encoder to another channel on the fly. + The new channel must have the same sample format (rate, channels, resolution) as the old channel, as that is what the encoder is expecting! + + + + + Returns the general channel info. + + + + + This property returns the actual bitwidth of the sample data of the channel (e.g. 8, 16, 32). + + BASS supports 8/16/32-bit sample data, so if a WAV file, for example, uses another sample resolution, it'll have to be converted by BASS. + This bitwidth represents the bitwidth which is used by BASS (e.g. in a DSP callback delegate) and does not represent the original bitwidth of the stream. + The bitwidth used by BASS is determined how the underlying channel handle was created (e.g. using with the or flag) + and if the option has been set. + If non of the above was used, by default 16 bits per sample are used. + However this bitwidth is the bitwidth in use when sending sample data to an encoder. + If for example the or the option have been used, + the encoder would receive 32-bit float samples. If the derived encoder implementation does not support floating-point sample data, + the encoder implementation should use one of the flags: BASS_ENCODE_FP_8BIT, BASS_ENCODE_FP_16BIT, BASS_ENCODE_FP_24BIT, BASS_ENCODE_FP_32BIT. + + + + + This property returns the actual sample rate in Hz of the sample data BASS is using with the channel (e.g. 44100). + + + + + This property returns the actual number of channles of the sample data BASS is using with the channel (e.g. 1=mono, 2=stereo, etc.). + + BASS supports multi-channel sample data, so make sure the actual encoder implementation supports multi-channel too. + If the encoder does not support multi-channel make sure that you are using non-multi-channel hanles only. + + + + + This property should return , if the base encoder implementation (resp. the underlying command-line tool being used) support STDOUT for output of the encoded data - else must be returned. + + In order to support broadcast streaming with an encoder command-line tool, + the encoded data needs to be received back by a callback function, so the encoder needs to be told to output to STDOUT (instead of a file). + + + + This property should return a value indicating which type of content the broadcast encoder implements. + + For example: If the implementation of the broadcast encoder implements an MP3 encoder, you should return BASS_CTYPE_STREAM_MP3. + For a complete list see . + + + + This property should return the default extension of an output file for this encoder (e.g. ".mp3" or ".ogg" etc.). + + + + + Gets or sets the current HENCODE encoder handle. + + The encoder handle will be set to a valid HENCODE handle, when the method was successfully called. + The encoder hande will be set to 0 (zero) when is called. + It is not advised to modify the encoder handle except in the actual implementation of the method. + + + + + Gets a value indicating if the encoder has been started (see ) and is active - else will be returned. + + This implementation first gets the . + If the encoder handle is valid (non-zero) the method is used to check the state. + If the state is not BASS_ACTIVE_STOPPED is returned. + In all other cases is returned (not started, paused, stopped etc.) + + + + Gets a value indicating if the encoder has been paused (see ) - else must be returned. + + This implementation first gets the . + If the encoder handle is valid (non-zero) the method is used to check the state. + Only if the state is BASS_ACTIVE_PAUSED this property returns . + In all other cases is returned (not started, active, playing etc.) + + + + Gets or Sets the encoder's base directory. + + This property might be used in the implementation to return a fully qualified path to the encoder executable within the command-line. + + + + This property should return an encoder command-line string, + which might be used with the method in order to create and start the encoder. + + Make sure, that the encoder command-line is evaluating the and members correctly. + Derived classes might also intruduce additional members which will have a direct impact of the command-line string. + Therefore the actual implementation of this property should always generate the command-line dynamically when this property is accessed. + + + + This property should return , if the encoder exists and is available - else should be returned. + + When using a command-line encoder this method might check, if the executable file exists in the specified . + + + + Gets or Sets the input file name to be processed by the encoder (null = STDIN, default). + + This member should be used when implementing the property. + + + + + Gets or Sets if a encoding in 16-bit sample data should be forced (default is ). + + This member should be used when implementing the property. + When you want to encode a floating-point channel, but the encoder does not support 32-bit floating-point sample data, then you can use this flags to have the sample data converted to 16 bit integer data before it's passed on to the encoder. + + + + + Gets or Sets if encoding should use the CAST_NOLIMIT flag (which is only needed, if the encoder is used for streaming). + + With this option you might disable the rate limiting during casting (as it'll be limited by the playback rate anyway if the source channel is being played). + + + + Gets or Sets if encoding should use an async queue (i.e. the BASS_ENCODE_QUEUE flag). + + + With this option you might enable queueing of sample data and feeding it to the encoder asynchronously in another thread, + so that any update thread isn't delayed by the encoding. + This might be usefull when encoding a playback stream or a recording stream which is feeding playback. + + + + + Gets or Sets the output file name to be processed by the encoder (null = STDOUT, default). + + This member should be used when implementing the property. + + + + This property should return the target effective bitrate of the encoder output (in kbps, e.g. 128 kbps). + + This member must return a valid bitrate (in kbps), if you are using the encoder in a implementation (i.e. the is set to ). + If an encoder implementation will never be used for broadcast streaming (or the is set to ) this property will not be used and mihgt not be overridden therefore. + If you are encoding in VBR or ABR this member must also return a valid bitrate (e.g. an approximated average). + You might use one of the constants in order to set a valid effective bitrate. + + + + + Gets or Sets the structure associated with the encoder. + + By default this member is - meaning no Tag info is used with the encoder. + If you set this property to a valid instance before you call , this will be used (when supported by the encoder) to automatically write the respective tag info to the output. + Meaning the will be modified accordingly. + The TAGs will only be used, if you have specified an . + + + + + List of supported encoding bitrates (kbps). + + Not all bitrates are supported for all sample frequencies. See the following table for an overview: + + MPEG-1 layer III sample frequencies (kHz): 32 44.1 48 + bitrates (kbps): 32 40 48 56 64 80 96 112 128 160 192 224 256 320 + MPEG-2 layer III sample frequencies (kHz): 16 22.05 24 + bitrates (kbps): 8 16 24 32 40 48 56 64 80 96 112 128 144 160 + MPEG-2.5 layer III sample frequencies (kHz): 8 11.025 12 + bitrates (kbps): 8 16 24 32 40 48 56 64 80 96 112 128 144 160 + AACplus sample frequencies (kHz): 32 44.1 48 + bitrates (kbps): 16 20 24 28 32 40 48 56 64 80 96 112 128 + aacPlusHigh additional bitrates (kbps): 160 192 224 256 320 + OGG sample frequencies (kHz): all from 8 to 96 + bitrates (kbps): 8 16 24 32 40 48 56 64 80 96 112 128 144 160 192 224 256 320 + WMA sample frequencies (kHz): 8 11.025 16 22 32 44.1 48 + bitrates (kbps): 6 8 10 12 16 20 22 32 40 48 64 80 96 128 160 192 256 320 + + + + + + 6kbps + + + + + 8kbps + + + + + 10kbps + + + + + 12kbps + + + + + 16kbps + + + + + 20kbps + + + + + 22kbps + + + + + 24kbps + + + + + 32kbps + + + + + 40kbps + + + + + 48kbps + + + + + 56kbps + + + + + 64kbps + + + + + 80kbps + + + + + 96kbps + + + + + 112kbps + + + + + 128kbps + + + + + 144kbps + + + + + 160kbps + + + + + 192kbps + + + + + 224kbps + + + + + 256kbps + + + + + 320kbps + + + + + List of supported broadcast sample rates. + + Make sure this samplerate matches your encoder settings. + + + + 8 kHz + + + + + 11.025 kHz + + + + + 16 kHz + + + + + 22.05 kHz + + + + + 32 kHz + + + + + 44.1 kHz + + + + + 48 kHz + + + + + 96 kHz + + + + + 192 kHz + + + + + This delegate might be used in the method. + + The total number of bytes to be encode. + The number of bytes already encoded. + + + + Encoder class implementation for the Windows Audio Compression Manager using . + + This class uses the encoder type (even if other types might be more propper). + Since Windows ACM does support 8-, 16-, and 32-bit(IEEE float) sample data as input, no BASS_ENCODE_FP_ flag will be used. + Make sure to set the ACM_xxx flags before calling . + This implementation uses the automatic DSP system for encoding. + Meaning the sending of sample data to the encoder is done automatically when you play the channel () or call (if it's a decoding channel). + So there is no need to call manually! + + If you simply want to encode a physical file please also take a look to the . + + + + + Creates an instance of a Windows ACM implementation. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + Implements ACM encoding. + This encoder might be used for streaming, since it does support STDOUT, however make sure to select an ACM codec matching your ! + + + + + Returns the name of the Encoder. + + E.g. returns "Audio Compression Manager (BASS_CTYPE_STREAM_WAV)". + + + + This method starts the actual ACM encoder. + + Optional callback function to receive the encoded data (only valid, if is set to )... = no callback. + User instance data to pass to the callback function. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Returns , if the encoder was successfully started - else is returned. + This method calls internally using the . + If you have specified a file name for (instead of ), a default stream using will be created internally and all it's data will immediately be encoded (meaning the flag will have no effect). + After the encoder was started successfully the returns a valid HENCODE handle. + If the encoder was not started successfully or was stopped returns 0 (zero). + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Saves the current to a file. + + The fully qualified file name and path where to save the . + Returns on success - else will be returned (e.g. is not specified or can not be accessed). + + + + Loads the from a file. + + The fully qualified file name and path from where to load the . + Returns on success - else will be returned (e.g. is not specified, can not be accessed or is invalid). + + + + Gets or Sets the ACM codec to be used. + + By default a standard WAVE_FORMAT_PCM (16-bit, stereo, 44.1kHz) ACM codec is selected. + You might modify the members in order to change a default WAVE_FORMAT_PCM codec (e.g. change the samplerate or bitwidth). + In order to load an already defined ACM codec format, make use of the method. + For more details see the ACM documentation: and . + + + + + If set, a WAVE header and the ACM codec content will be written to the (default is ). + + This is generally required for the file to be playable, but in some cases (a Non-Wave ACM codec was selected, e.g. MP3) this is not wanted. + So set this property to for all Non-Wave ACM codecs. + Note: This property will only be evaluated, if the is set to BASS_CTYPE_STREAM_WAV and the is not set to . + If the is not set to BASS_CTYPE_STREAM_WAV or the is set to , a WAVE header will never be written. + + + + + Gets or Sets the which will be supported by the encoder. + + + + + Gets or Sets the default output extension to be used by the encoder (e.g. ".wav"). + + + + + This property always return , since ACM should be installed on every Windows platform. + + + + + Gets a value indicating the type of content. Here the value is returned. + + + + + This return the default extension of an output file for this encoder (e.g. ".wav"). Here the value is returned. + + + + + ACM does implement STDOUT, so is always returned. + + This encoder might be used for streaming, since it does support STDOUT. + However, the selected ACM codec must match the implementation! + + + + Returns an empty string, since ACM does not use any command-line tool, but instead directly used . + + + + + Returns the effective encoder bitrate (in kbps) of the output. + + This implementation evaluates the structure (nAvgBytesPerSec) in order to calculate the effective bitrate. + + + + Encoder class implementation for the RIFF WAVE format using raw PCM sample data with no real encoder. + + This class uses the encoder type. + This format supports 8-, 16- and 32-bit(IEEE float) sample data as input. + Make sure to set the WAV_xxx and/or BWF_xxx flags before calling . + TAG writing is supported by saving appropriate RIFF LIST INFO chunks. + This implementation uses the automatic DSP system for encoding. + Meaning the sending of sample data to the encoder is done automatically when you play the channel () or call (if it's a decoding channel). + So there is no need to call manually! + + If you simply want to encode a physical file please also take a look to the . + + + Manual encoding "File" To "File" in 32-bit: + + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, + BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT); + EncoderWAV w = new EncoderWAV(stream); + w.InputFile = null; + w.OutputFile = "test.wav"; // will be a 32-bit IEEE float WAVE file, since the stream is float + w.Start(null, IntPtr.Zero, false); + // do the encoding + Utils.DecodeAllData(stream, true); + w.Stop(); + + + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, + BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT) + Dim w As New EncoderWAV(stream) + w.InputFile = Nothing + w.OutputFile = "test.wav" ' will be a 32-bit IEEE float WAVE file, since the stream is float + w.Start(Nothing, IntPtr.Zero, False) + ' do the encoding + Utils.DecodeAllData(stream, True) + w.Stop() + + Manual encoding "File" To "File" in 24-bit: + + EncoderWAV w = new EncoderWAV(0); + w.InputFile = "testIn.wav"; + w.OutputFile = "testOut.wav"; + w.WAV_BitsPerSample = 24; + w.Start(null, IntPtr.Zero, false); + w.Stop(); + + + Dim w As New EncoderWAV(0) + w.InputFile = "testIn.wav" + w.OutputFile = "testOut.wav" + w.WAV_BitsPerSample = 24 + w.Start(Nothing, IntPtr.Zero, False) + w.Stop() + + "Recording" To "File" in 16-bit: + + private RECORDPROC _recProc; + + // init your recording device (we use the default device) + if ( !Bass.BASS_RecordInit(-1) ) + MessageBox.Show(this, "Bass_RecordInit error!" ); + _recProc = new RECORDPROC(RecordingHandler); + // start recording at 44.1kHz, stereo (paused) + int recHandle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, _recProc, IntPtr.Zero); + if (recHandle == Bass.FALSE) + MessageBox.Show(this, "BASS_RecordStart error!" ); + + // setup the encoder + EncoderWAV w = new EncoderWAV(recHandle); + w.InputFile = null; + w.OutputFile = "testrec.wav"; + w.Start(null, IntPtr.Zero, true); // start encoder paused + ... + // now really start recording and encoding + w.Pause(false); + Bass.BASS_ChannelPlay(recHandle, false); + ... + // your recording will be encoded until you call + w.Stop(); + + private bool RecordingHandler(int handle, IntPtr buffer, int length, IntPtr user) + { + return true; + } + + + private RECORDPROC _recProc; + + ' init your recording device (we use the default device) + If Not Bass.BASS_RecordInit(- 1) Then + MessageBox.Show(Me, "Bass_RecordInit error!") + End If + _recProc = New RECORDPROC(AddressOf RecordingHandler) + ' start recording at 44.1kHz, stereo (paused) + Dim recHandle As Integer = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, _recProc, IntPtr.Zero) + If recHandle = Bass.FALSE Then + MessageBox.Show(Me, "BASS_RecordStart error!") + End If + + ' setup the encoder + Dim w As New EncoderWAV(recHandle) + w.InputFile = Nothing + w.OutputFile = "testrec.wav" + w.Start(Nothing, IntPtr.Zero, True) ' start encoder paused + ... + ' now really start recording and encoding + w.Pause(False) + Bass.BASS_ChannelPlay(recHandle, False) + ... + ' your recording will be encoded until you call + w.Stop() + + Private Function RecordingHandler(handle As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Boolean + Return True + End Function + + + + + + Creates an instance of a RIFF WAVE implementation. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + Implements RIFF WAVE encoding. + This encoder might be used for streaming, since it does support STDOUT. + + + + + Returns the name of the Encoder. + + E.g. returns "RIFF WAVE (BASS_CTYPE_STREAM_WAV)". + + + + This method starts the actual WAV encoder. + + Must be = no callback, since EncoderWAV does not support STDOUT. + Must be , since EncoderWAV does not support STDOUT. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Returns , if the encoder was successfully started - else is returned. + This method uses the BASS_ENCODE_PCM flag to write plain PCM sample data to a file (if an has been specified), without an encoder. + If no has been specified () - nothing will actually happen. + If you have specified a file name for (instead of ), a default stream using will be created internally and all it's data will immediately be encoded (meaning the flag will have no effect), + else the data from the will be encoded. + After the encoder was started successfully the returns a valid HENCODE handle. + If the encoder was not started successfully or was stopped returns 0 (zero). + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Gets or Sets the which will be supported by the encoder. + + + + + Gets or Sets the default output extension to be used by the encoder (e.g. ".wav"). + + + + + Gets a value indicating the type of content. Here the value is returned. + + + + + This return the default extension of an output file for this encoder (e.g. ".wav"). Here the value is returned. + + + + + WAV does not implement STDOUT, so is always returned. + + This encoder might not be used for streaming, since it does not support STDOUT. + + + + Returns the , since WAV does not use any command-line tool. + + + + + Returns the effective encoder bitrate (in kbps) of the output. + + This implementation evaluates the original , and the in order to calculate the effective bitrate. + + + + Always returns false, since this encoder doesn't supports this flag. The target format can be set via the property. + + + + + Gets or Sets the target resolution (number of bits per sample) of the Wave file to create - + (by default the original resolution will be used). + + This property is only evaluated, if an has been specified or the BASS_CONFIG_FLOATDSP option is set! + NOTE: In all other cases the original resolution will be used! + This property should be either 8, 16, 24 or 32. + + + + + Gets or Sets, if 32bit integer (instead of 32bit IEEE float) should be used when setting to 32 (default is )? + + When seeting this property to and setting the property to 32, the 32bit integer wave format is used - + else the 32bit IEEE float is used as the default 32bit format. + + + + + Gets or Sets, if a RIFF INFO LIST chunk should be written to the file (default is )? + + The presense of a structure is required to write the RIFF INFO LIST chunk to the file. + + + + + Gets or Sets, if a BWF RF64 WAVE header should be used instead of a regular WAVE header (default is )? + + + + + Gets or Sets, if a BWF BEXT chunk should be written to the file (default is )? + + The presense of a structure is required to write the BEXT chunk to the file. + When writing a BWF BEXT chunk to the file, the native tags with the prefix BWF are being used. + + + + + Gets or Sets, if a BWF CART chunk should be written to the file (default is )? + + The presense of a structure is required to write the CART chunk to the file. + When writing a BWF BEXT chunk to the file, the native tags with the prefix BWF are being used. + + + + + Encoder class implementation for any generic Command-Line encoder tool using . + + This class uses by default the encoder type (even if other types might be more propper) - so make sure to set the property accordingly. + Also the is by default set to ".wav" and needs to be changed if needed (see all CMDLN_xxx properties). + Since this is a generic implementation this encoder will try to use either 32-bit float, 24-bit, 16-bit or 8-bit sample data (depending on the and the or property). + The flags will be used, if you set the flag. + You MUST set the property to the executable name you want to use. Also make sure that the and the are configured accordingly. + The encoder will receive, raw PCM sample data in little endian. + Make sure to set the CMDLN_xxx flags before calling . + This implementation uses the automatic DSP system for encoding. + Meaning the sending of sample data to the encoder is done automatically when you play the channel () or call (if it's a decoding channel). + So there is no need to call manually! + + If you simply want to encode a physical file please also take a look to the . + + + + + Creates an instance of the generic command-line encoder implementation. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + Implements generic command-line encoding. + This encoder might be used for streaming only if the property is set to true and the underlying executable does support STDOUT as well - however make sure to select a command-line tool matching your ! + + + + + Returns the name of the Encoder. + + Eg.: returns "Generic Command-Line Encoder". + + + + This method starts the actual command-line encoder. + After the encoder was started successfully the returns a valid HENCODE handle. + + Optional callback function to receive the encoded data (only valid, if is set to )... = no callback. + User instance data to pass to the callback function. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Returns , if the encoder was successfully started - else is returned. + This method calls internally! + After the encoder was started successfully the returns a valid HENCODE handle. + If the encoder was not started successfully or was stopped returns 0 (zero). + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Gets or Sets if the encoder should be started using the NOHEAD flag. + + + + + Gets or Sets if the encoder should be started using the FP_32BIT flag. + + The flag will only be evaluated, if this flag is not set (). + + + + Gets or Sets if the encoder should be started using the FP_24BIT flag. + + If the flag is set () this flag will be ignored. + + + + Gets or Sets the command-line executable name to be used with the encoder (not containing the path, e.g. "encoder.exe"). + + You MUST set this parameter! + + + + Gets or sets the ${output} parameter to be used with STDOUT. + + + + + Gets or sets the ${input} parameter to be used with STDIN. + + + + + Gets or Sets the which will be supported by the encoder. + + + + + Gets or Sets the default output extension to be used by the encoder (e.g. ".mp3"). + + + + + Gets or Sets if the encoder supports output of the encoded data to STDOUT. + + + + + Gets or Sets, if the or the command-line string should be used. + + + + + + Gets or Sets the constant bitrate (CBR) command-line string to be used with the encoder (not containing the executable to be used, e.g. "-b ${bps} - output.xyz"). + + This command-line string is used, if is set to . + + + + Gets or Sets the variable bitrate (VBR) command-line string to be used with the encoder (not containing the executable to be used, e.g. "-b ${bps} - output.xyz"). + + This command-line string is used, if is set to . + + + + Gets or Sets the effective bitrate (in kbps) for the ${bps} and ${kbps} macro to be used with the resp. . + + Only needed when this encoder will be used for a or if you use the ${kbps} or ${bps} macro in or . + + + + Gets or Sets the ${quality} macro value to be used in the resp. . + + Might e.g. contain the encoding quality level to be used. + + + + Gets or Sets the ${mode} macro value to be used in the resp. . + + Might e.g. contain the stereo mode (joint-stereo, mono, dual channel, independent stereo etc.) to be used. + + + + Gets or Sets the ${option} macro value to be used in the resp. . + + Might e.g. contain any other optional value to be used. + + + + Gets or Sets, if the or the macro string should be used. + + If set to the macro value is used - else the macro value is used. + + + + Gets or Sets the ${user} macro value to be used in the resp. . + + This is a general purpose macro placeholder, which is only used, if the property is set to . + + + + Gets or Sets the ${user} macro value to be used in the resp. . + + This is a general purpose macro placeholder, which is only used, if the property is set to . + + + + This property return , if the specifiec command-line tool is availabel - else . + + + + + Gets a value indicating the type of content. Here the value is returned. + + + + + This return the default extension of an output file for this encoder (e.g. ".wav"). Here the value is returned. + + + + + A command-line encoder might implement STDOUT, so here the value is returned. + + This encoder might be used for streaming, since it might support STDOUT. + However, the selected command-line encoder must match the implementation! + + + + Returns the specified command-line string to use. Depending on the property the or the value is evaluated and all contained macros are replaced. + + + + + Returns the effective encoder bitrate (in kbps) of the output. Here the value is returned. + + The effective bitrate value is only needed, if the encoder is used for a . This member otherwise will never be really used. + + + + Encoder class implementation for any generic MP3 command-line encoder tool using . + + This class uses by default the encoder type ( is set to ".mp3"). + This encoder is directly derived from - so please take a look there for all other details. + + + + + Creates an instance of the generic MP3 command-line encoder implementation. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + Implements generic command-line encoding. + This encoder might be used for streaming only if the property is set to true (which is by default the case) and the underlying executable does support STDOUT as well - however make sure to select a command-line tool matching your ! + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Returns the name of the Encoder. + + Eg.: returns "Generic MP3 Encoder". + + + + Encoder class implementation for MP3 encoding using lame.exe. + + This class uses the encoder type. + LAME (lame.exe) must be downloaded separately (e.g. from www.rarewares.org). + Since lame.exe does not support 32-bit IEEE float sample data as input, the BASS_ENCODE_FP_32BIT will be used for highest quality. + This will be used, whenever the underlying channel handle is 32-bit float or the BASS_CONFIG_FLOATDSP option has been set. + Make sure to set the LAME_xxx flags before retrieving the or calling . + This implementation uses the automatic DSP system for encoding. + Meaning the sending of sample data to the encoder is done automatically when you play the channel () or call (if it's a decoding channel). + So there is no need to call manually! + + If you simply want to encode a physical file please also take a look to the . + + + + + Creates an instance of a LAME encoder implementation. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + LAME implements MP3 encoding (BASS_CTYPE_STREAM_MP3). + + + + Returns the name of the Encoder. + + Returns "LAME Encoder (BASS_CTYPE_STREAM_MP3)". + + + + This method starts the actual LAME encoder. + + Optional callback function to receive the encoded data (only valid, if is set to )... = no callback. + To have the encoded data received by a callback function, the encoder needs to be told to output to STDOUT (instead of a file), so must return true. + User instance data to pass to the callback function. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Returns , if the encoder was successfully started - else is returned. + This method calls internally using the . + After the encoder was started successfully the returns a valid HENCODE handle. + If the encoder was not started successfully or was stopped returns 0 (zero). + This implementation starts the encoder with the BASS_ENCODE_NOHEAD and BASSEncode.BASS_ENCODE_FP_32BIT flag. + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Use the parameter string only (default=). + + Caution: If set to no other LAME_xxx options will be evaluated and ONLY the parameter string will be used! + + + + The custom parameter string, which should be used, if the property is set to . + + This property string will be appended to all other LAME_xxx options, if the property is set to (default). + + + + -m: The encoding mode (stereo, joint stereo, mono etc.). + + + + + --scale: Scale input (multiply PCM data). Set to 1.00 (default) for no scaling. + + + + + --preset: Preset name must be "medium", "standard", "extreme", "insane" or a value for an average desired bitrate + and depending on the value specified, appropriate quality settings will be used. + + If a preset name is specified NO other options will be used! + So make sure to set the preset name to String.Empty, if you want to use any other options. + + + + Noise shaping and psycho acoustic algorithms (default is Quality). + + + + + --replaygain: ReplayGain analysis (Default is None). + + + + + --freeformat: produce a free format bitstream? (Default is ). + + + + + -b: Constant (or minimum allowed) bitrate in kbps, default 128 kbps. + + + If the flag is not set (): This specifies the CBR bitrate. + If the flag is set (): This specifies the minimum allowed VBR bitrate, if is also set. + + + + + --resample: target sampling frequency of output (in Hz). Set to 0 (zero) to use automatic resampling (default). + + Specify the target sample rate in Hz, e.g. 22050 for 22.05kHz. + When using this encoder for broadcast streaming it is advised to always set the target samplerate. + You might use one of the constants here. + + + + + --cbr: Enforce use of constant bitrate. + + Only evaluated, if the flag is not set (). + + + + --abr: Specify average target bitrate in kbps desired (instead of quality). + Set to 0, if this option should be disabled (default). + + Only evaluated, if the flag is set (). + + + + Use variable bitrate (VBR) (Default is ). + + If enabled, the or value will be used. + + + + Use variable bitrate (VBR) limitation (Default is ). + + If , the and values will be used as the minimum and maximum allowed VBR bitrate, + as well as the flag will be evaluated. + + + + -V: Quality setting for VBR (default is VBR_Q4). + + + + + Specify maximum allowed bitrate in kbps, default 320 kbps. + + Only evaluated, if the flag is set (). + + + + -t: disable writing VBR LAME Tag? (Default is ). + + Only evaluated, if the flag is set (). + + + + -F: strictly enforce minimum bitrate, for use with players that do not support low bitrate mp3. + + Only evaluated, if the flag is set (). + + + + -c: mark as copyright (default=). + + + + + -o: mark as non-original (default=). + + + + + -p: error protection. Adds 16-bit checksum to every frame (default=). + + + + + --nores: disable the bit reservoir (default=). + + + + + --strictly-enforce-ISO: comply as much as possible to ISO MPEG spec (default=). + + + + + -k: keep ALL frequencies (disables all filters), can cause ringing and twinkling (default=). + + + + + --short: use short blocks when appropriate (default=). + + + + + --noshort: don't use short blocks (default=). + + + + + --allshort: use only short blocks (default=). + + + + + --notemp: disable temporal masking effect (default=). + + + + + --nssafejoint: M/S switching criterion (default=). + + + + + --noasm: disable assembly optimizations for mmx/3dnow/sse. + + + + + --highpass: frequency(kHz), highpass filter cutoff below freq. + + Set to 0 (zero) to apply default (disabled). + + + + --highpass-width: frequency(kHz) - default 15% of highpass freq. + + Set to 0 (zero) to apply the default. + + + + --lowpass: frequency(kHz), lowpass filter cutoff above freq. + + Set to 0 (zero) to apply default (disabled). + + + + --lowpass-width: frequency(kHz) - default 15% of lowpass freq. + + Set to 0 (zero) to apply the default. + + + + --ath...: ATH control. + + + + + This property return , if the file "lame.exe" exists in the - else is returned. + + + + + Gets a value indicating the type of content. Here BASS_CTYPE_STREAM_MP3 is always returned. + + + + + This return the default extension of an output file for this encoder (".mp3"). + + + + + LAME implements STDOUT, so is always returned. + + LAME support boradcast streaming. + + + + Gets the actual encoder command-line string (using all LAME_xxx properties). + + The encoder command-line is evaluating the and members + as well as the LAME_xxx settings. + + + + Returns the effective encoder bitrate (in kbps) of the output. + + If you are encoding in CBR ( is set to , default) the member will be returned. + If you are encoding in VBR or ABR ( is set to ) the average of and resp. will be used. + + + + + LAME ATH control options. + + + + + Default: standrad ATH control + + + + + --athonly: Ignore output of PSY model, only use masking from ATH (not recommended, use only for testing). + + + + + --noath: Disable ATH. + + + + + --athshort: use ATH only for short blocks. + + + + + --noasm: Assembly optimizations options. + + + + + Default: mmx/3dnow/sse are enabled. + + + + + MMX will be disabled. + + + + + 3dNOW will be disabled. + + + + + SSE will be disabled. + + + + + -V: Quality setting for VBR (default is VBR_Q4). + + + + + -V 0: high quality, bigger files. + + + + + -V 1 + + + + + -V 2 + + + + + -V 3 + + + + + -V 4: default. + + + + + -V 4 + + + + + -V 5 + + + + + -V 6 + + + + + -V 7 + + + + + -V 9: poor quality, smaller files. + + + + + ReplayGain analysis. + + + + + Default, use no option. + + + + + Compute RG fast but slightly inaccurately (default). + + + + + Compute RG more accurately and find the peak sample. + + + + + Disable ReplayGain analysis. + + + + + Encoding quality (default is Quality). + + + + + -q 0: Highest quality, slow + + + + + -q 1 + + + + + -q 2, same as -h + + + + + -q 3 + + + + + -q 4 + + + + + -q 5, default + + + + + -q 6 + + + + + -q 7, same as -f + + + + + -q 8 + + + + + -q 9: poor quality, fast + + + + + None + + + + + -f: Fast, equals -q 7 + + + + + -h: Default quality, recommended, equals -q 2 + + + + + The general LAME encoding mode (stereo, joint stereo, mono etc.). + + + + + Default is JointStereo or Stereo depending on bitrate. + + + + + Stereo + + + + + Force LR stereo on all frames + + + + + Force MS stereo on all frames + + + + + Mono + + + + + Dual Mono + + + + + Encoder class implementation for MP3 encoding using the Fraunhofer IIS mp3 Surround command line encoder mp3sEncoder.exe. + + This class uses the encoder type. + mp3sEncoder (mp3sEncoder.exe) must be downloaded separately (e.g. from www.all4mp3.com). + Since mp3sEncoder.exe does not support 32-bit IEEE float sample data as input, the BASS_ENCODE_FP_24BIT will be used for highest quality. + This will be used, whenever the underlying channel handle is 32-bit float or the BASS_CONFIG_FLOATDSP option has been set. + Make sure to set the MP3S_xxx flags before retrieving the or calling . + This implementation uses the automatic DSP system for encoding. + Meaning the sending of sample data to the encoder is done automatically when you play the channel () or call (if it's a decoding channel). + So there is no need to call manually! + + If you simply want to encode a physical file please also take a look to the . + + + + + Creates an instance of a mp3sEncoder implementation. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + mp3sEncoder implements MP3 encoding (BASS_CTYPE_STREAM_MP3). + + + + Returns the name of the Encoder. + + Returns "Fraunhofer IIS MP3 Surround Encoder (BASS_CTYPE_STREAM_MP3)". + + + + This method starts the actual mp3sEncoder. + + Optional callback function to receive the encoded data (only valid, if is set to )... = no callback. + To have the encoded data received by a callback function, the encoder needs to be told to output to STDOUT (instead of a file), so must return true. + User instance data to pass to the callback function. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Returns , if the encoder was successfully started - else is returned. + This method calls internally using the . + After the encoder was started successfully the returns a valid HENCODE handle. + If the encoder was not started successfully or was stopped returns 0 (zero). + This implementation starts the encoder with the BASS_ENCODE_NOHEAD and BASSEncode.BASS_ENCODE_FP_24BIT flag. + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Use the parameter string only (default=). + + Caution: If set to no other MP3S_xxx options will be evaluated and ONLY the parameter string will be used! + + + + The custom parameter string, which should be used, if the property is set to . + + This property string will be appended to all other MP3S_xxx options, if the property is set to (default). + + + + -mono: Create mono downmix from stereo input file before encoding? (default=). + + + + + -q: Use high quality encoder setting? (default=). + + + + + -b: Constant bitrate in kbps, default 128 kbps. + + + Valid ranges for the output bitrate are: + Mono mp3: 16000 - 256000 bits/s + Stereo mp3: 96000 - 320000 bits/s + MP3 Surround: 128000 - 320000 bits/s + + + + + Use variable bitrate (VBR) (Default is ). + + If enabled, the value will be used. + + + + -m: Quality setting for VBR (default is High). + + + + + -vbri: Write a VBRI header? (Default is ). + + Only evaluated, if the flag is set (). + + + + This property return , if the file "mp3sEncoder.exe" exists in the - else is returned. + + + + + Gets a value indicating the type of content. Here BASS_CTYPE_STREAM_MP3 is always returned. + + + + + This return the default extension of an output file for this encoder (".mp3"). + + + + + Fraunhofer IIS MP3 Surround implements STDOUT, so is always returned. + + mp3sEncoder support boradcast streaming. + + + + Gets the actual encoder command-line string (using all MP3S_xxx properties). + + The encoder command-line is evaluating the and members + as well as the MP3S_xxx settings. + + + + Returns the effective encoder bitrate (in kbps) of the output. + + Actually this will always return the member. + + + + + -m: Quality setting for VBR. + + + + + -m 1: highest quality + + + + + -m 2: high quality + + + + + -m 3: intermediate quality + + + + + -m 4: intermediate bitrate + + + + + -m 5: low bitrate + + + + + Encoder class implementation for Winamp AACplus encoding using "enc_aacPlus.exe" (the command-line encoder using the following Winamp DLLs: "enc_aacplus.dll", "nscrt.dll" and "libmp4v2.dll"). + + This class uses the encoder type. + Please make sure to use the special "enc_aacPlus.exe" version (made by Bernd Niedergesäß) which can be downloaded here: enc_aacPlus.zip. + Since "enc_aacPlus.exe" also needs the mentioned Winamp DLLs ("enc_aacplus.dll", "nscrt.dll" and and "libmp4v2.dll" as of version 5.57 or above) you also need to install Winamp and copy the Winamp DLLs from the Winamp/PlugIns folder into the same folder which contains enc_aacPlus.exe (or you might also copy enc_aacPlus.exe into the Winamp/PlugIns folder). + Since the Winamp AACPlus library does only support 16-bit sample data as input, the BASS_ENCODE_FP_16BIT will always be used. Also note, that 8-bit sample data is also not supported! + This will be used, whenever the underlying channel handle is float or the BASS_CONFIG_FLOATDSP option has been set. + Make sure to set the AACPlus_xxx flags before retrieving the or calling . + This encoder does not support 8-bit channels! + This implementation uses the automatic DSP system for encoding. + Meaning the sending of sample data to the encoder is done automatically when you play the channel () or call (if it's a decoding channel). + So there is no need to call manually! + + The extension of the can be either .acc to write an aac bitstream output file or .m4a/.mp4 to box the output to a MP4 container (note, that using m4a/mp4 requires "libmp4v2.dll" to be present). + If you simply want to encode a physical file please also take a look to the . + + + + + Creates an instance of a Winamp AACplus encoder implementation. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + This encoder implements AACplus v2 encoding (BASS_CTYPE_STREAM_AAC). + This encoder does not support 8-bit channels! + + 8-bit channels are not supported by the Winamp AACPlus encoder. + + + + Returns the name of the Encoder. + + Returns "Winamp AACPlus v2 Encoder (BASS_CTYPE_STREAM_AAC)". + + + + This method starts the actual AACplus encoder. + + Optional callback function to receive the encoded data (only valid, if is set to )... = no callback. + To have the encoded data received by a callback function, the encoder needs to be told to output to STDOUT (instead of a file), so must return true. + User instance data to pass to the callback function. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Returns , if the encoder was successfully started - else is returned. + This method calls internally using the . + After the encoder was started successfully the returns a valid HENCODE handle. + If the encoder was not started successfully or was stopped returns 0 (zero). + This implementation starts the encoder with the BASS_ENCODE_NOHEAD and BASSEncode.BASS_ENCODE_FP_16BIT flag. + So floating-point channels are supported and automatically converted - but 8-bit channels are not supported!. + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Determines, if Winamp is installed on your machine. + + is returned if Winamp is installed - else is returned. + + + + --br: bitrate in kbps, default 128 kbps. + + + + + --ps: Enable Parametric Stereo (bitrates up to 56000, only with HE-AAC, default=). + + + + + --is: Independed Stereo, disables Joint Stereo M/S coding (default=). + + + + + --dc: Prefer Dual Channel (default=). + + + + + --mono: Encode as Mono (default=). + + + + + --mpeg2aac: Force MPEG2 AAC instead of letting the encoder choose (default=). + + + + + --mpeg4aac: Force MPEG4 AAC instead of letting the encoder choose (default=). + + + + + --lc: Encode as LC-AAC (supports bitrate up to 320000, default=). + + LC-AAC requires encoding to a physical output file, so it will not be supported, if you output to STDOUT. + + + + --he: Encode as HE-AAC (supports bitrate up to 128000, default=). + + + + + --high: Encode as HE-AAC+ with high bitrates (supports bitrate up to 256000, multichannel not supported, default=). + + + + + --speech: Tune for Speech encoding (default=). + + + + + --pns: Enable Perceptual Noise Subsitution (default=). + + + + + Box the output to a MP4 container using the .m4a output file extension (default=). + + Setting this flag to requires the "libmp4v2.dll" to be present. + This flag is automatically applied when encoding to an output file with the extension '.m4a' or '.mp4'. + + + + + This property return , if the files "enc_aacPlus.exe" and "enc_aacplus.dll" exists in the - else is returned. + + To check, if Winamp is also installed you might call the method. + + + + Gets a value indicating the type of content. Here BASS_CTYPE_STREAM_AAC is always returned. + + + + + This return the default extension of an output file for this encoder (either ".aac" or ".m4a"). + + + + + The special "enc_aacPlus.exe" implements STDOUT, so is always returned. + + Please make sure to use the special "enc_aacPlus.exe" version (made by Bernd Niedergesäß). + It can be downloaded from here: enc_aacPlus.zip + + + + Gets the actual encoder command-line string (using all AACPlus_xxx properties). + + The encoder command-line is evaluating the and members + as well as the AACPlus_xxx settings. + + + + Returns the effective encoder bitrate (in kbps) of the output. + + Since AACPlus does not support VBR, the effective bitrate is always given by the member. + + + + Always returns true, since this encoder only supports receiving 16 bit sample data. + + 32-bit float channels are supported, since they are automatically converted to 16-bit integer sample data before sending them to the encoder. + + + + Encoder class implementation for FHG Winamp AACplus encoding using "fhgaacenc.exe" (the command-line encoder using the following Winamp DLLs: "enc_fhgaac.dll", "nsutil.dll", "libsndfile-1.dll" and "libmp4v2.dll"). + + This class uses the encoder type. + fhgaacenc (fhgaacenc.exe) must be downloaded separately (e.g. from https://github.com/tmkk/fhgaacenc). + Since "fhgaacenc.exe" also needs the mentioned Winamp DLLs ("enc_fhgaac.dll", "nsutil.dll" and "libmp4v2.dll" as of version 5.62 or above) you also need to install Winamp and copy the Winamp DLLs from the Winamp resp. Winamp/PlugIns folder + into the same folder which contains fhgaacenc.exe (or you might also copy "fhgaacenc.exe" and "libsndfile-1.dll" into the Winamp/PlugIns folder). + The FHG Winamp AACPlus library does not support 32-bit floating point sample data as input, so the BASS_ENCODE_FP_32BIT flag will automatically be used. + Make sure to set the AACPlus_xxx flags before retrieving the or calling . + This implementation uses the automatic DSP system for encoding. + Meaning the sending of sample data to the encoder is done automatically when you play the channel () or call (if it's a decoding channel). + So there is no need to call manually! + + The extension of the can be either .acc to write an aac bitstream output file or .m4a/.mp4 to box the output to a MP4 container (note, that using m4a/mp4 requires "libmp4v2.dll" to be present). + If you simply want to encode a physical file please also take a look to the . + + + + + Creates an instance of a FHG Winamp AACplus encoder implementation. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + This encoder implements AACplus v2 encoding (BASS_CTYPE_STREAM_AAC). + + + + + Returns the name of the Encoder. + + Returns "FHG Winamp AACPlus v2 Encoder (BASS_CTYPE_STREAM_AAC)". + + + + This method starts the actual FHG AACplus encoder. + + Optional callback function to receive the encoded data (only valid, if is set to )... = no callback. + To have the encoded data received by a callback function, the encoder needs to be told to output to STDOUT (instead of a file), so must return true. + User instance data to pass to the callback function. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Returns , if the encoder was successfully started - else is returned. + This method calls internally using the . + After the encoder was started successfully the returns a valid HENCODE handle. + If the encoder was not started successfully or was stopped returns 0 (zero). + This implementation starts the encoder with the BASS_ENCODE_FP_32BIT flag. So floating-point channels are supported and automatically converted. + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Determines, if Winamp is installed on your machine. + + is returned if Winamp is installed - else is returned. + + + + --cbr: encode in CBR mode; bitrate in kbps (8..576), default 128 kbps. + + + CBR mode is used by default unless you set the property to a value greater than 0 (zero). + + + + + --vbr: encode in VBR mode; preset 1..5, default is 0 (disabled). + + + When set to 0 (zero) VBR mode is disabled and the CBR mode is used (see ). + When set to a value between 1 and 5 CBR mode is disabled and VBR mode is used. + + + + + --profile: choose the AAC profile (only for CBR mode); default is Auto. + + + Auto : automatically choose the optimum profile according to the bitrate (default). + LC : force use LC-AAC profile. + HE : force use HE-AAC (AAC+SBR) profile. + HEv2 : force use HE-AAC v2 (AAC+SBR+PS) profile. + + + + + Use ADTS container instead of MPEG-4. + + Setting this flag to requires the "libmp4v2.dll" to be present. + Encoding to STDOUT ( is set to ) requires this flag to be set (e.g. when streaming to a SHOUTcast server in AAC), + in such case this flag is automatically applied. + + + + + This property return , if the files "fhgaacenc.exe", "enc_fhgaac.dll", "libsndfile-1.dll" and "nsutil.dll" exists in the - else is returned. + + To check, if Winamp is also installed you might call the method. + + + + Gets a value indicating the type of content. Here BASS_CTYPE_STREAM_AAC is always returned. + + + + + This return the default extension of an output file for this encoder (either ".aac" or ".m4a"). + + + + + The "fhgaacenc.exe" implements STDOUT, so is always returned. + + + + + Gets the actual encoder command-line string (using all AACPlus_xxx properties). + + The encoder command-line is evaluating the and members + as well as the AACPlus_xxx settings. + + + + Returns the CBR encoder bitrate (in kbps) of the output. + + Note: This property always returns the CBR mode bitrate as given by the member. + + + + The FHG AAC profile to use (only for CBR mode). + + + + + Automatically choose the optimum profile according to the bitrate [default]. + + + + + Force use LC-AAC profile. + + + + + Force use HE-AAC (AAC+SBR) profile. + + + + + Force use HE-AAC v2 (AAC+SBR+PS) profile. + + + + + Encoder class implementation for OGG-Vorbis encoding using "oggenc2.exe". + + This class uses the encoder type. + "oggenc2.exe" must be downloaded separately (e.g. from www.rarewares.org or www.vorbis.com). + Since "oggenc2.exe" does support 8/, 16/ and 32-bit(IEEE float) sample data as input, no BASS_ENCODE_FP_ flag will be used. + Make sure to set the OGG_xxx flags before retrieving the or calling . + There are several versions of "oggenc.exe" or "oggenc2.exe" out there (some are highly optimized for SSE etc.). + This encoder implementation tries to support the latest version 2.x set of parameters. If you downloaded another OGG-Vorbis encoder version, just try it out and simply make sure that you rename the executable to "oggenc2.exe". + This implementation uses the automatic DSP system for encoding. + Meaning the sending of sample data to the encoder is done automatically when you play the channel () or call (if it's a decoding channel). + So there is no need to call manually! + + If you simply want to encode a physical file please also take a look to the . + + + + + Creates an instance of a OGG encoder implementation. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + Implements OGG encoding (BASS_CTYPE_STREAM_OGG). + + + + Returns the name of the Encoder. + + Returns "OGG Encoder (BASS_CTYPE_STREAM_OGG)". + + + + This method starts the actual OGG encoder. + + Optional callback function to receive the encoded data (only valid, if is set to )... = no callback. + To have the encoded data received by a callback function, the encoder needs to be told to output to STDOUT (instead of a file), so must return true. + User instance data to pass to the callback function. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Returns , if the encoder was successfully started - else is returned. + This method calls internally using the . + After the encoder was started successfully the returns a valid HENCODE handle. + If the encoder was not started successfully or was stopped returns 0 (zero). + This implementation starts the encoder with the BASS_ENCODE_NOHEAD flag. + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Converts a quality setting (between -2.0 and 10.0) to an approx. bitrate (in kbps). + + The OGG quality level to convert (between -2.0 and 10.0). + The rounded approximate bitrate in kbps. + + + + Converts a bitrate (between 32 kbps and 498 kbps) to an approx. quality level. + + The bitrate in kbps to convert (between 32 kbps and 498 kbps). + The OGG quality level (between -2.0 and 10.0) which approximates the bitrate. + + + + Use the parameter string only (default=). + + Caution: If set to no other OGG_xxx options will be evaluated and ONLY the parameter string will be used! + + + + The custom parameter string, which should be used, if the property is set to . + + This property string will be appended to all other OGG_xxx options, if the property is set to (default). + + + + --downmix: Downmix from stereo to mono? (default is ). + + + + + --scale: Scale input data to n (n = between 0.00 and 1.00, multiply PCM data). Set to 1.0 (default) for no scaling. + + + + + Use Quality-Mode? (default is ). + + + When using the Quality-Mode ( is set to , default) you only specify a quality factor via and the bitrate parameters (, and ) are ignored. + When you turn off Quality-Mode ( is set to ) the bitrate parameters are evaluated! + + + + + -q: Specify quality between -2 (low) and 10 (high) (default=4), instead of specifying a particular bitrate (). + + This is the normal, default mode of operation. Fractional qualities (e.g. 2.75) are permitted. + If you enable the Quality-Mode ( is set to , default) only this value is being evaluated. + If you disable the Quality-Mode ( is set to ) this value is being ignored. + Here is a list about approximate Quality to Bitrate mappings: + + Quality:Bitrate: + -2approx. 32 kbps + -1approx. 48 kbps + 0approx. 64 kbps + 1approx. 80 kbps + 2approx. 96 kbps + 3approx. 112 kbps + 4approx. 128 kbps + 5approx. 160 kbps + 6approx. 192 kbps + 7approx. 224 kbps + 8approx. 256 kbps + 9approx. 320 kbps + 10approx. 498! kbps + + + + + + + -b: Choose a nominal bitrate to encode at. Attempt to encode at a bitrate averaging this. Takes an argument in kbps. + + By default, this produces a VBR encoding, equivalent to using -q or --quality. + See the option to use a managed bitrate targetting the selected bitrate. + Unless the is set to this property is NOT evaluated. + To use ABR (average bitrate): set and to 0 (zero). + To use CBR (constant bitrate): specify the exact same value also for and . + + + + + --managed: Enable the bitrate management engine. This will allow much greater control over the precise bitrate(s) used, but encoding will be much slower. + Don't use it unless you have a strong need for detailed control over bitrate, such as for streaming. + + This property is not evaluated unless you set to . + + + + -m: Specify a minimum bitrate (in kbps). Useful for encoding for a fixed-size channel. If set to 0 (zero, default) this property is not evaluated! + + Unless the is set to this property is NOT evaluated. + To use ABR (average bitrate): set and to 0 (zero) and only specify a value for . + To use CBR (constant bitrate): specify the exact same value as you set for also for and . + + + + + -M: Specify a maximum bitrate in kbps. Useful for streaming applications. If set to 0 (zero, default) this property is not evaluated! + + Unless the is set to this property is NOT evaluated. + To use ABR (average bitrate): set and to 0 (zero) and only specify a value for . + To use CBR (constant bitrate): specify the exact same value as you set for also for and . + + + + + --resample: target sampling frequency of output (in Hz). Set to 0 (zero) if you don't want to do any resampling (default). + + Specify the target sample rate in Hz, e.g. 22050 for 22.05kHz. + You might use one of the constants here. + Use the property to control which resampling engine should be used. + + + + + -S: Specify the resampling engine to be used. Options are: Best, Medium (default) and Fast. + + Will only be used, if you have specified a which is not 0 (zero). + + + + This property return , if the file "oggenc2.exe" exists in the - else is returned. + + + + + Gets a value indicating the type of content. Here BASS_CTYPE_STREAM_OGG is always returned. + + + + + This return the default extension of an output file for this encoder (".ogg"). + + + + + "oggenc2.exe" implements STDOUT, so is always returned. + + "oggenc2.exe" support boradcast streaming. + + + + Gets the actual encoder command-line string (using all OGG_xxx properties). + + The encoder command-line is evaluating the and members + as well as the OGG_xxx settings. + + + + Returns the effective encoder bitrate (in kbps) of the output. + + + When using the Quality-Mode ( is set to , default) you only need to specify a quality factor via and the bitrate parameters (, and ) are ignored. + In this case the effective bitrate will be calculated automatically according to the OGG-Vorbis specification. + When you turn off Quality-Mode ( is set to ) the bitrate parameters are evaluated! + However, no matter if you are encoding in CBR ( is set to ) or VBR/ABR ( is set to , default) the properties and will not be used - instead only the value will be used to return the effective bitrate value. + + + + + The OGG resampling engine mode (Best, Medium. Fast). + + + + + Best resampling quality. + + + + + Medium resampling quality (default). + + + + + Fast resampling, low quality. + + + + + Encoder class implementation for the Nero Digital AAC encoder using "neroAacEnc.exe". + + This class uses the encoder type. + The NeroAac Encoder must be downloaded separately (e.g. from www.nero.com). + Since "neroAacEnc.exe" does support 8-, 16-, and 32-bit(IEEE float) sample data as input, no BASS_ENCODE_FP_ flag will be used. + Make sure to set the NERO_xxx flags before retrieving the or calling . + There are two versions: "neroEncAac.exe" and "neroAacEnc_sse2.exe" out there (one is highly optimized for SSE etc.). + This encoder implementation supports both versions see the property for details. + This implementation uses the automatic DSP system for encoding. + Meaning the sending of sample data to the encoder is done automatically when you play the channel () or call (if it's a decoding channel). + So there is no need to call manually! + + If you simply want to encode a physical file please also take a look to the . + + + + + Creates an instance of a Nero Digital AAC encoder implementation. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + Implements AAC encoding (BASS_CTYPE_STREAM_AAC). + This encoder can NOT be used for streaming, since it does not support STDOUT! + + + + + Returns the name of the Encoder. + + Returns "Nero Digital Aac Encoder (BASS_CTYPE_STREAM_AAC)". + + + + This method starts the actual Nero Digial Aac encoder. + + Must be always = no callback - since this encoder does NOT support STDOUT. + N/A - ignorred. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Returns , if the encoder was successfully started - else is returned. + This method calls internally using the . + After the encoder was started successfully the returns a valid HENCODE handle. + If the encoder was not started successfully or was stopped returns 0 (zero). + This implementation starts the encoder with no flags, meaning a Wave header will be send to the encoder to specify the bitrate, number of channels and samplerate. + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Specifies, if the "neroAacEnc.exe" (, default) or the "neroAacEnc_sse2.exe" () command-line tool should be used. + + + + + Use the parameter string only (default=). + + Caution: If set to no other NERO_xxx options will be evaluated and ONLY the parameter string will be used! + + + + The custom parameter string, which should be used, if the property is set to . + + This property string will be appended to all other NERO_xxx options, if the property is set to (default). + + + + Use Quality-Mode? (default is ). + + + When using the Quality-Mode ( is set to ) you only specify a quality factor via and the bitrate parameter () is ignored. + When you turn off Quality-Mode ( is set to , default) the bitrate parameter is evaluated and the parameter is ignored! + + + + + -q: Specify quality between 0.00 (low) and 1.00 (high) (default=0.4), instead of specifying a particular bitrate (). + + This is an alternative mode of operation. Fractional qualities (e.g. 0.75) are permitted. + If you enable the Quality-Mode ( is set to ) only this value is being evaluated. + If you disable the Quality-Mode ( is set to , default) this value is being ignored. + Here is a list about approximate Quality to Bitrate mappings: + + Quality:Bitrate: + 0.0approx. 13 kbps + 0.1approx. 25 kbps + 0.2approx. 52 kbps + 0.3approx. 83 kbps + 0.4approx. 130 kbps + 0.5approx. 180 kbps + 0.6approx. 227 kbps + 0.7approx. 269 kbps + 0.8approx. 316 kbps + 0.9approx. 362 kbps + 1.0approx. 408! kbps + + + + + + + -br: Choose a nominal bitrate to encode at. Attempt to encode at a bitrate averaging this. Takes an argument in kbps. + + By default, this produces a VBR encoding. + See the option to use a managed bitrate targetting a constant bitrate. + Unless the is set to this property is NOT evaluated. + + + + + -cbr: Enables the constant bitrate mode (default is ). When enabled CBR is generated, else VBR is generated. + + This property is not evaluated unless you set to . + + + + -2pass: Enables two-pass encoding mode. Note that two-pass mode requires a physical file as input, rather than STDIN. + + This property is only evaluated, if an is being used. + + + + -2passperiod: Overrides two-pass encoding bitrate averaging period, in milliseconds. Specify 0 (zero) to use least restrictive value possible (default). + + This property is only evaluated, if is set to . + + + + -lc: Forces use of LC AAC profile, HE features disabled (default is ). + + Note that the switches (-lc, -he, -hev2) should not be used. + Optimal AAC profile is automatically determined from quality/bitrate settings when no override is specified. + + + + + -he: Forces use of HE AAC profile, HEv2 features disabled (default is ). + + Note that the switches (-lc, -he, -hev2) should not be used. + Optimal AAC profile is automatically determined from quality/bitrate settings when no override is specified. + + + + + -hev2: Forces use of HEv2 AAC profile (default is ). + + Note that the switches (-lc, -he, -hev2) should not be used. + Optimal AAC profile is automatically determined from quality/bitrate settings when no override is specified. + + + + + -hinttrack: Generates an RTP hint track in output MP4 file (default is ). + + + + + This property return , if the file "neroAacEnc.exe" or "neroAacEnc_sse2.exe" (depending on your setting) exists in the - else is returned. + + + + + Gets a value indicating the type of content. Here BASS_CTYPE_STREAM_AAC is always returned. + + + + + This return the default extension of an output file for this encoder (".m4a"). + + + + + Nero Digital Aac does NOT implement STDOUT, so FASLE is always returned. + + This encoder can NOT be used for streaming, since it does not support STDOUT! + + + + Gets the actual encoder command-line string (using all NERO_xxx properties). + + The encoder command-line is evaluating the and members + as well as the NERO_xxx settings. + + + + Returns the effective encoder bitrate (in kbps) of the output. + + + No matter if you are encoding in CBR (see ) or VBR (default) the properties value will be used to return the effective bitrate value. + + + + + Encoder class implementation for the QuickTime AAC encoder using "qtaacenc.exe". + + This class uses the encoder type. + The QuickTime AAC Encoder must be downloaded separately (e.g. from here). + Since "qtaacenc.exe" does support 8-, 16-, and 32-bit(IEEE float) sample data as input, no BASS_ENCODE_FP_ flag will be used. + Make sure to set the QT_xxx flags before retrieving the or calling . + Note: QuickTime v7.6.4 or higher and maybe the VC2008 runtime needs to be installed on your machine. + This implementation uses the automatic DSP system for encoding. + Meaning the sending of sample data to the encoder is done automatically when you play the channel () or call (if it's a decoding channel). + So there is no need to call manually! + + If you simply want to encode a physical file please also take a look to the . + + + + + Creates an instance of a QuickTime AAC encoder implementation. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + Implements AAC encoding (BASS_CTYPE_STREAM_AAC). + This encoder can NOT be used for streaming, since it does not support STDOUT! + + + + + Returns the name of the Encoder. + + Returns "QuickTime AAC Encoder (BASS_CTYPE_STREAM_AAC)". + + + + This method starts the actual QuickTime AAC encoder. + + Must be always = no callback - since this encoder does NOT support STDOUT. + N/A - ignorred. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Returns , if the encoder was successfully started - else is returned. + This method calls internally using the . + After the encoder was started successfully the returns a valid HENCODE handle. + If the encoder was not started successfully or was stopped returns 0 (zero). + This implementation starts the encoder with no flags, meaning a Wave header will be send to the encoder to specify the bitrate, number of channels and samplerate. + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Determines, if QuickTime is installed on your machine. + + is returned if QuickTime is installed - else is returned. + + + + Use the parameter string only (default=). + + Caution: If set to no other QT_xxx options will be evaluated and ONLY the parameter string will be used! + + + + The custom parameter string, which should be used, if the property is set to . + + This property string will be appended to all other QT_xxx options, if the property is set to (default). + + + + Gets or Sets which encoder quality mode to use? (default is High). + + + + + --cbr, --abr, --cvbr or --tvbr: Gets or Sets the QuickTime encoding mode (CBR, ABR, CVBR, TVBR). + + + + + + + + --cbr, --abr or --cvbr: Choose a nominal bitrate to encode at for the selected (only used for CBR, ABR and CVBR). + Attempt to encode at a bitrate averaging this. Takes an argument in kbps. + + By default, this produces a CBR encoding. + This property is only evaluated if the is set to CBR, ABR or CVBR. + + + + + --tvbr: Choose the quality value for the selected (only used for TVBR). + Available quality range is 0-127 (default is 65). + + + This property is only evaluated if the is set to TVBR. + + + + + --he: Enable the high efficiency (HE-AAC) encoder. Cannot be used with True VBR mode. + + + + + --samplerate: Control the samplerate of the output file. + + Use one of the following values: + -1: Automatically choose the optimum samplerate according to the bitrate and quality. + 0: Keep the original samplerate (if possible, default). + value: Specify the preferred samplerate in Hz. Allowed values are: 8000, 11250, 12000, 16000, 22050, 24000, 32000, 44100, 48000. + + + + + This property return , if the file "qtaacenc.exe" exists in the - else is returned. + + To check, if QuickTime is also installed you might call the method. + + + + Gets a value indicating the type of content. Here BASS_CTYPE_STREAM_AAC is always returned. + + + + + This return the default extension of an output file for this encoder (".m4a"). + + + + + QuickTime AAC does NOT implement STDOUT, so FASLE is always returned. + + This encoder can NOT be used for streaming, since it does not support STDOUT! + + + + Gets the actual encoder command-line string (using all QT_xxx properties). + + The encoder command-line is evaluating the and members + as well as the QT_xxx settings. + + + + Returns the effective encoder bitrate (in kbps) of the output. + + + No matter in which you are encoding, the properties value will be used to return the effective bitrate value. + + + + + The QuickTime encoding mode (CBR, ABR, CVBR, TVBR). + + + + + Encode in CBR mode. Available bitrate range is 16-320kbps(stereo), 8-256kbps(mono). + + + + + Encode in ABR mode. Available bitrate range is 16-320kbps(stereo), 8-256kbps(mono). + + + + + Encode in Constrained VBR mode. Available bitrate range is 16-320kbps(stereo), 8-256kbps(mono). + + + + + Encode in True VBR mode. Available quality range is 0-127 (default). + + + + + The QuickTime quality engine mode (Fast, Normal, High). + + + + + Choose the profile for the fastest encoding speed (identical to --fast in the current QT AAC encoder). + + + + + Choose the profile focused on the encoding speed. + + + + + Choose the profile with moderate speed and quality. + + + + + Choose the profile focused on the encoding quality (default). + + + + + Choose the profile for the highest encoding quality (identical to --high in the current QT AAC encoder). + + + + + Encoder class implementation for the Windows Media Audio codec using . + + This class uses the encoder type. + Since WMA does support 8-, 16-, and 32-bit(IEEE float) sample data as input, no BASS_ENCODE_FP_ flag will be used. + Make sure to set the WMA_xxx flags before calling . + As with all encoders in this framework also this WMA encoder always automatically encodes sample data (by using a DSP callback). So there is no need to manually send any sample data to the encoder. + The property can be used to setup a to receive notifications about the encoder status (e.g. when the encoder died). + IMPORTANT NOTE: This implementation uses BASSwma. So make sure the BASSwma add-on and dll is available. + + + Manual encoding of a stream (here in lossless format): + + int stream = Bass.BASS_StreamCreateFile("test.wav", 0, 0, BASSFlag.BASS_STREAM_DECODE); + EncoderWMA wma = new EncoderWMA(stream); + wma.WMA_UseVBR = true; + wma.WMA_VBRQuality = 100; // lossless + wma.InputFile = null; //STDIN + wma.OutputFile = "test.wma"; + wma.Start(null, IntPtr.Zero, false); + // encode all the data right away + Utils.DecodeAllData(stream, true); + wma.Stop(); + + + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.wav", 0, 0, BASSFlag.BASS_STREAM_DECODE) + Dim wma As New EncoderWMA(stream) + wma.WMA_UseVBR = True + wma.WMA_VBRQuality = 100 ' lossless + wma.InputFile = Nothing 'STDIN + wma.OutputFile = "test.wma" + wma.Start(Nothing, IntPtr.Zero, False) + ' encode all the data right away + Utils.DecodeAllData(stream, True) + wma.Stop() + + Automatic encoding to the local network (using a recording handle): + + EncoderWMA wma = new EncoderWMA(_recHandle); + wma.WMA_UseVBR = false; + wma.WMA_Bitrate = 64; + wma.WMA_UsePro = true; + wma.WMA_UseNetwork = true; + wma.WMA_NetworkPort = 80; + wma.WMA_NetworkClients = 10; + wma.InputFile = null; //STDIN + wma.OutputFile = null; //STDOUT + wma.Start(null, IntPtr.Zero, false); + ... + // encodes until this is called + wma.Stop(); + + + Dim wma As New EncoderWMA(_recHandle) + wma.WMA_UseVBR = False + wma.WMA_Bitrate = 64 + wma.WMA_UsePro = True + wma.WMA_UseNetwork = True + wma.WMA_NetworkPort = 80 + wma.WMA_NetworkClients = 10 + wma.InputFile = Nothing 'STDIN + wma.OutputFile = Nothing 'STDOUT + wma.Start(Nothing, IntPtr.Zero, False) + ... + ' encodes until this is called + wma.Stop() + + + + + + Creates an instance of a Windows Media Audio encoder implementation. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + Implements WMA encoding. + This encoder might be used for streaming, since it does support STDOUT, however make sure to select an WMA codec matching your implementation! + Please note, that there is also a special implementation. + + + + + Stops the encoder (if started). + + Returns , if the encoder was successfully stopped - else is returned. + Internally is called using the . + After the encoder was stopped successfully the is set to 0 (zero). + If the encoder was not stopped the is left unchanged. + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Pauses or resumes an encoder + + = pause the encoder, = resume the encoder. + Will always return . + Since WMA does not natively support pausing/resuming of the encoder, this special implementation will suppress writing data to the encoder while the encoder is paused. + + + + Returns the name of the Encoder. + + Returns "Audio Compression Manager (BASS_CTYPE_STREAM_WAV)". + + + + This method starts the actual WMA encoder. + + Optional callback function to receive the encoded data... = no callback. + User instance data to pass to the callback function. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Returns , if the encoder was successfully started - else is returned. + This method calls , , or (resp. or if the was set) internally depending on the and properties. + If you have specified a file name for (instead of ), a default stream using will be created internally and all it's data will immediately be encoded (meaning the flag will have no effect). + After the encoder was started successfully the returns a valid HENCODE handle. + If the encoder was not started successfully or was stopped returns 0 (zero). + The is only used, if you have set the property to and are encoding to STDOUT ( must be ). + If in such case the is invoked you need to be aware of one special WMA case: + When encoding begins, an initial header is given. When encoding is completed, an updated header is given (the initial header should be replaced by the updated one). + The WMA header can be recognized by a negative 'length' parameter, whereas positive 'length' values will indicate plain WMA encoded data. + + Internally, the sending of sample data to the encoder is implemented via a DSP callback on the channel. + That means when you play the channel (or call if it's a decoding channel), the sample data will be sent to the encoder at the same time. + So in contrast to the standard BASSwma implementation there is no need to manually feed (write) any sample data to the encoder. + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + You might use the property to get informed when this happens. + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Sets a tag in a WMA encoding. + + The tag to set. + The standard WMA header tags are as follows: + + TitleContent title. + AuthorName of the content author (Artist). + DescriptionDescription of the content. + RatingContent rating. + CopyrightContent copyright message. + WM/AlbumTitleAlbum title. + WM/PromotionURLURL to an HTML page containing related information. + WM/AlbumCoverURLURL to an HTML page containing an image of the album cover. + WM/GenreGenre of the music. + WM/YearYear of publication of the music. + + + The tag's text/data. + on success, else . + + + + Choose a total bitrate to encode at. Takes an argument in kbps (default is 128 kbps). + + By default, this produces a CBR encoding. + To use VBR (variable bitrate): set to and specify a . + To use CBR (constant bitrate): set to (default). + + + + + Use 24-bit encoding? (Default is ). + + If set to , the output will be in 24-bit resolution. + The WMA codec expects 16-bit or 24-bit sample data, but BASSWMA will accept 8-bit, 16-bit or floating-point data, and convert it to the appropriate format. + Of course, it makes little sense to encode 8-bit or 16-bit data in 24-bit. + When this parameter is set to the WMA 10 Professional codec will be used automatically (regardless of the setting). + + + + + Use the WMA 10 Professional format? (Default is = WMA 9 format). + + Windows Media Audio 10 Professional (WMA 10 Pro) is the most flexible Windows Media audio codec available – supporting profiles that include everything from full-resolution 24-bit/96 kHz audio in stereo, 5.1 channel, or even 7.1 channel surround sound, to highly efficient mobile capabilities at 24 Kbps to 96 Kbps for stereo, and 128 Kbps to 256 Kbps for 5.1-channel sound. WMA 10 Pro offers incredible quality for consumers using high-fidelity hardware and 5.1 channel surround sound-equipped computers -– and for consumers playing audio content on their mobile devices. WMA 10 Pro supports streaming, progressive download, or download-and-play delivery at 128 to 768 Kbps. + WMA Pro also offers dynamic range control using the maximum and average audio amplitudes that are calculated during the encoding process. Using the Quiet Mode feature in Windows Media Player 9 and later, users can hear either the full dynamic range, a medium difference range up to 12 decibels (dB) above the average, or a little difference range up to 6 dB above the average. + If a user tries to play back a file that was encoded using the 5.1 channel, 24-bit, 96 kHz sampling capabilities, but does not have a system or sound card that supports multi-channel or high-resolution sound, multiple channels are combined into stereo audio (for example, 16-bit, two channel audio), ensuring that users get the best playback experience their systems can provide. + + + + + When set to , the WMA standard codec (WMA 9) will be forced to use (default is ). + + If neither this or the flag is specified, then either codec (WMA 9 or WMA 10 Pro) could be used (whichever supports the requested sample format and bitrate). + If the flag is set to , the and options will not be evaluated! + + + + + Enable the VBR (variable bitrate) mode (default is ). + + If not set to the CBR (constant bitrate) mode will be used. + When making a VBR stream, the bitrate is only allowed to vary within set limits: + + Samplerate:Bitrate: + 48kHzStereo: 112-384kbps Mono: 56-192kbps + 44.1kHz or 32kHzStereo: 192-384kbps Mono: 96-192kbps + 24kHz, 22.05kHz or 16kHzStereo/Mono: 8-160kbps + + + + + + + Set a VBR quality level from 1 (very low) to 100 (lossless). + + The higher the number the better the quality. + If the is set to , this property is not evaluated! + VBR and lossless encoding are currently only available at 44100hz stereo (48000hz too, but with limited quality settings). + To encode other sample formats, the data will first have to be resampled before. + Here is a list of quality level to approximate kbps mapping: + + Quality:Bitrate: + 10%65 kbps + 25%77 kbps + 50%89 kbps + 75%140 kbps + 100%778 kbps + + + + + + + Currently only used internally. + + + + + Currently only used internally. + + + + + Enables WMA encoding to the network (default is ). + + When encoding to a network it will not be possible to receive the encoded data (see ). + However, you might use the streaming server implementation in this case. + Also note, that if streaming to a network you must set the properties: and optionally . + If you set the property to (default), encoding will directly be done to the network (pull mode): users might connect directly to the specified . + Set the property to , in order to enable encoding to a publishing point on a Windows Media server (push mode). + If you are using this encoder in the class, there will be no need to set this member, since it will automatically be done by the class implementation! + + + + + Enables WMA encoding to a publishing point on a Windows Media server. + + This property will only be evaluated, if is set to . + When encoding to a network it will not be possible to receive the encoded data (see ). + However, you might use the streaming server implementation in this case. + Also note, that if streaming to a Windows Media server you must set the properties: , and . + If you set the property to (default), encoding will directly be done to the network (pull mode): users might connect directly to the specified . + Set the property to , in order to enable encoding to a publishing point on a Windows Media server (push mode). + If you are using this encoder in the class, there will be no need to set this member, since it will automatically be done by the class implementation! + + + + + Here you can specify an array of encoding bitrates (in bits per second!) to use in case you selected or - default is . + + If set to the multi bitrate option for network encoding or encoding to a publishing point on a Windows Media server is not used, but only the is evaluated. + If you assign an array of bitrates (in bits per second!) here (e.g. = new int[2] {64000, 128000}) these bitrates will be used instead on the property! + This property will only be evaluated in case you set or to . + If you are using this encoder in the class, there will be no need to set this member, since it will automatically be done by the class implementation! + + + + + The network port number for clients to conenct to (only used, if is set to and is set to ) - default is 8080. + + + If you are using this encoder in the class, there will be no need to set this member, since it will automatically be done by the class implementation! + + + + + The maximum number of clients (up to 50) that can be connected (only used, if is set to and is set to ) - default is 1. + + + If you are using this encoder in the class, there will be no need to set this member, since it will automatically be done by the class implementation! + + + + + URL of the publishing point on the Windows Media server. + + This property is only evaluated, if is set to . + If you are using this encoder in the class, there will be no need to set this member, since it will automatically be done by the class implementation! + + + + + Username to use in connecting to the server. + + If either this or is , then no username/password is sent to the server. + This property is only evaluated, if is set to . + If you are using this encoder in the class, there will be no need to set this member, since it will automatically be done by the class implementation! + + + + + Password to use in connecting to the server. + + If either this or is , then no username/password is sent to the server. + This property is only evaluated, if is set to . + If you are using this encoder in the class, there will be no need to set this member, since it will automatically be done by the class implementation! + + + + + Gets a value indicating if the encoder has been started (see ) and is active - else will be returned. + + This implementation first gets the . + If the encoder handle is valid (non-zero) will be returned. In all other cases is returned. + + + + Gets a value indicating if the encoder has been paused (see ) - else will be returned. + + While the encoder is paused no data will be written to the encoder, however the input channel is not paused. + + + + This property always return , since we use the native BASSWMA add-on. + + Make sure to have "basswma.dll" available in your path. + + + + Gets a value indicating the type of content. Here BASS_CTYPE_STREAM_WAV is always returned. + + Since it will actually be impossible to return the real ACM codec related channel type, we will instead always use Here BASS_CTYPE_STREAM_WAV. + + + + This return the default extension of an output file for this encoder (".wma"). + + + + + WMA does implement STDOUT, so is always returned. + + This encoder might be used for streaming, since it does support STDOUT. + However, the selected WMA codec must match the implementation! + Please note, that there is also a special implementation. + + + + + Returns an empty string, since WMA does not use any command-line tool, but instead directly uses the add-on. + + + + + Returns the effective encoder bitrate (in kbps) of the output. + + This implementation always returns the member. + + + + Always returns false, since this encoder doesn't supports this flag. Use the property instead. + + + + + Gets the total bytes send to the server. + + + + + Gets ot Sets a on the WMA encoder. + + + A WMA encoder can only have one notification callback set. Subsequent calls to this property can be used to change the callback, or disable notifications (). + The WMA encoder's status can be one of the following (see ): + + BASS_ENCODE_NOTIFY_ENCODERThe encoder died. + BASS_ENCODE_NOTIFY_CASTCast server connection died (or any other mystery problem). + + + + + + + Encoder class implementation for MPEG Audio Layer II (MP2) encoding using "tooLAME.exe". + + This class uses the encoder type. + "tooLAME.exe" must be downloaded separately (e.g. from www.rarewares.org or toolame.sourceforge.net). + tooLAME is a very good and stable freeware MP2 encoder. + Since tooLAME does only support 16-bit sample data as input, the BASS_ENCODE_FP_16BIT flag will be used. + This will be used, whenever the underlying channel handle is float or the BASS_CONFIG_FLOATDSP option has been set. + Make sure to set the TWO_xxx flags before retrieving the or calling . + This implementation uses the automatic DSP system for encoding. + Meaning the sending of sample data to the encoder is done automatically when you play the channel () or call (if it's a decoding channel). + So there is no need to call manually! + + If you simply want to encode a physical file please also take a look to the . + + + + + Creates an instance of a tooLAME encoder implementation. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + Implements MP2 encoding (BASS_CTYPE_STREAM_MP2). + + + + Returns the name of the Encoder. + + Returns "tooLAME Encoder (BASS_CTYPE_STREAM_MP2)". + + + + This method starts the actual tooLAME encoder. + After the encoder was started successfully the returns a valid HENCODE handle. + + Optional callback function to receive the encoded data... = no callback. + To have the encoded data received by a callback function, the encoder needs to be told to output to STDOUT (instead of a file), so must return true. + User instance data to pass to the callback function. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Returns , if the encoder was successfully started - else is returned. + This method calls internally using the . + After the encoder was started successfully the returns a valid HENCODE handle. + If the encoder was not started successfully or was stopped returns 0 (zero). + This implementation starts the encoder with the BASS_ENCODE_NOHEAD and BASS_ENCODE_FP_16BIT flag. + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Use the parameter string only (default=). + + Caution: If set to no other TOO_xxx options will be evaluated and ONLY the parameter string will be used! + + + + The custom parameter string, which should be used, if the property is set to . + + This property string will be appended to all other TOO_xxx options, if the property is set to (default). + + + + -m: The encoding mode (Stereo, Joint stereo, DualChannel, Mono, default is Auto). + + For MPEG Audio Layer II, not all combinations of total bitrate and mode are allowed. See the following table: + + Bitrate (kbps):Allowed Modes: + 32, 48, 56mono only + 64all modes + 80mono only + 96, 112, 128, 160, 192all modes + 224, 256, 320, 384stereo only + + + + + + -a: Downmix from stereo to mono? (default is ). + + + + + -b: Choose a total bitrate to encode at. Takes an argument in kbps (default is 192 kbps). + + By default, this produces a CBR encoding. + To use VBR (variable bitrate): set to and specify a . + To use CBR (constant bitrate): set to (default). + + + + + Enable the VBR (variable bitrate) mode (default is ). + + If not set to the CBR (constant bitrate) mode will be used. + When making a VBR stream, the bitrate is only allowed to vary within set limits: + + Samplerate:Bitrate: + 48kHzStereo: 112-384kbps Mono: 56-192kbps + 44.1kHz or 32kHzStereo: 192-384kbps Mono: 96-192kbps + 24kHz, 22.05kHz or 16kHzStereo/Mono: 8-160kbps + + + + + + + -v: Enable VBR and set a quality level from -50 to 50 (default is disbaled). + + The higher the number the better the quality. Maximum range is -50 to 50 but useful range is -10 to 10. See vbr documentation file for details. + If the is set to , this property is not evaluated! + Using for example "-v -5" will force the encoder to favour the lower bitrate. Whereas using "-v 5" will force the encoder to favour the upper bitrate. + The value can actually be any number. The larger the number, the greater the bitrate bias. + + + + + -P: The psychoacoustic model (PAM) tooLAME should use (-1 to 4). + + Choose the psycho-acoustic model to use (-1 to 4). Model number -1 turns off psycho-acoustic modelling and uses fixed default values instead. + + + + -l: Set the ATH level. Default level is 0.0 (which will not use the property). + + ATH means Absolute Thresholds of Hearing. The ATH value raises/lowers the ATH by this many dB. + + + + -q: Enable quick mode (if value is geater than 0 (zero)). Only re-calculate psycho-acoustic model every specified number of frames (default is 0). + + + + + -c: Turn on Copyright flag in output bitstream (default is ). + + + + + -o: Mark as Original in output bitstream (default is ). + + + + + -e: Enable CRC error protection in output bitstream. An extra 16-bit checksum is added to each frame (default is ). + + + + + -r: force padding bit/frame off (default is ). + + + + + -d: Set the de-emphasis type (None, CCIT, 50/15ms). Default is None. + + + + + -D: Add DAB extensions of specific length (specify 0 (zero) to not specify a DAB extension, default). + + + + + This property return , if the file "tooLAME.exe" exists in the - else is returned. + + + + + Gets a value indicating the type of content. Here BASS_CTYPE_STREAM_MP2 is always returned. + + + + + This return the default extension of an output file for this encoder (".mp2"). + + + + + tooLAME implements STDOUT, so is always returned. + + tooLAME support boradcast streaming. + + + + Gets the actual encoder command-line string (using all TOO_xxx properties). + + The encoder command-line is evaluating the and members + as well as the TOO_xxx settings. + + + + Returns the effective encoder bitrate (in kbps) of the output. + + + No matter if you are using CBR- or VBR-Mode (see ) the value will be used to return the effective bitrate value. + + + + + Always returns true, since this encoder only supports receiving 16 bit sample data. + + 32-bit float channels are supported, since they are automatically converted to 16-bit integer sample data before sending them to the encoder. + + + + The general tooLAME encoding mode (stereo, joint stereo, mono etc.). + + + + + Default is JointStereo or Stereo depending on bitrate. + + + + + Stereo + + + + + Force LR stereo on all frames + + + + + Force dual channel all frames + + + + + Mono + + + + + The psychoacoustic model tooLAME should use (-1 to 4, default is 1). + + + + + Default model will be selected by encoder. + + + + + Psychoacoustic Model: -1 (turns off psycho-acoustic modelling and uses fixed default values instead) + This PAM doesn't actually look at the samples being encoded to decide upon the output values. There is simply a set of 32 default values which are used, regardless of input. + Pros: Faaaast. Low complexity. Surprisingly good. "Surprising" in that the other PAMs go to the effort of calculating FFTs and subbands and masking, and this one does absolutely nothing. Zip. Nada. Diddly Squat. This model might be the best example of why it is hard to make a good model - if having no computations sounds OK, how do you improve on it? + Cons: Absolutely no attempt to consider any of the masking effects that would help the audio sound better. + + + + + Psychoacoustic Model: 0 + This PAM looks at the sizes of the scalefactors for the audio and combines it with the Absolute Threshold of Hearing (ATH) to make the 32 SMR values. + Pros: Faaast. Low complexity. + Cons: This model has absolutely no mathematical basis and does not use any perceptual model of hearing. It simply juggles some of the numbers of the input sound to determine the values. + + + + + Psychoacoustic Model: 1 + This PAM is from the ISO standard. Just because they are the standard, doesn't mean that they are any good. Look at LAME which basically threw out the MP3 standard psycho models and made their own (GPSYCHO). + Pros: A reference for future PAMs. + Cons: Terrible ISO code, buggy tables, poor documentation. + + + + + Psychoacoustic Model: 2 + This PAM is from the ISO standard. Just because they are the standard, doesn't mean that they are any good. Look at LAME which basically threw out the MP3 standard psycho models and made their own (GPSYCHO). + Pros: A reference for future PAMs. + Cons: Terrible ISO code, buggy tables, poor documentation. + + + + + Psychoacoustic Model: 3 + A re-implementation of psychoacoustic model 1. ISO11172 was used as the guide for re-writing this PAM from the ground up. + Pros: No more obscure tables of values from the ISO code. Hopefully a good base to work upon for tweaking PAMs. + Cons: At the moment, doesn't really sound any better than PAM1. + + + + + Psychoacoustic Model: 4 + A cleaned up version of PAM2. + Pros: Faster than PAM2. No more obscure tables of values from the ISO standard. Hopefully a good base to work from for improving the PAMs. + Cons: Still has the same "warbling"/"Davros" problems as PAM2. + + + + + The general tooLAME encoding mode (stereo, joint stereo, mono etc.). + + + + + No Emphasis + + + + + Emphasis according to CCIT J.17 + + + + + Emphasis 50/15 ms + + + + + Encoder class implementation for MP2 TwoLAME encoding using "twolame.exe". + + This class uses the encoder type. + "twolame.exe" must be downloaded separately (e.g. from www.rarewares.org or www.twolame.org). TwoLAME is a fork of the tooLAME project, so don't mix it up. TwoLAME is a very good and stable freeware MP2 encoder. + Make sure to set the TWO_xxx flags before retrieving the or calling . + This implementation uses the automatic DSP system for encoding. + Meaning the sending of sample data to the encoder is done automatically when you play the channel () or call (if it's a decoding channel). + So there is no need to call manually! + + If you simply want to encode a physical file please also take a look to the . + + + + + Creates an instance of a TwoLAME encoder implementation. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + Implements MP2 encoding (BASS_CTYPE_STREAM_MP2). + + + + Returns the name of the Encoder. + + Returns "TwoLAME Encoder (BASS_CTYPE_STREAM_MP2)". + + + + This method starts the actual TwoLAME encoder. + After the encoder was started successfully the returns a valid HENCODE handle. + + Optional callback function to receive the encoded data... = no callback. + To have the encoded data received by a callback function, the encoder needs to be told to output to STDOUT (instead of a file), so must return true. + User instance data to pass to the callback function. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Returns , if the encoder was successfully started - else is returned. + This method calls internally using the . + After the encoder was started successfully the returns a valid HENCODE handle. + If the encoder was not started successfully or was stopped returns 0 (zero). + This implementation starts the encoder with the BASS_ENCODE_NOHEAD flag and if your input is 32-bit float the BASS_ENCODE_FP_32BIT flag is used. + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Use the parameter string only (default=). + + Caution: If set to no other TWO_xxx options will be evaluated and ONLY the parameter string will be used! + + + + The custom parameter string, which should be used, if the property is set to . + + This property string will be appended to all other TWO_xxx options, if the property is set to (default). + + + + -m: The encoding mode (Stereo, Joint stereo, DualChannel, Mono, default is Auto). + + + + + --scale: Scale input data (multiply PCM data). Set to 1.0 (default) for no scaling. + + + + + -a: Downmix from stereo to mono? (default is ). + + + + + -b: Choose a total bitrate to encode at. Takes an argument in kbps (default is 256 kbps). + + By default, this produces a CBR encoding. + To use VBR (variable bitrate): set to and optionally specify a value. + To use CBR (constant bitrate): set to (default). The value will be ignored in this case. + + + + + -B: Specify a maximum bitrate in kbps when in VBR mode. + + If set to 0 (zero, default) or if the is set to , this property is not evaluated! + + + + -v: Enable the VBR (variable bitrate) mode (default is ). + + If not set to the CBR (constant bitrate) mode will be used. + When making a VBR stream, the bitrate is only allowed to vary within set limits: + + Samplerate:Bitrate: + 48kHzStereo: 112-384kbps Mono: 56-192kbps + 44.1kHz or 32kHzStereo: 192-384kbps Mono: 96-192kbps + 24kHz, 22.05kHz or 16kHzStereo/Mono: 8-160kbps + + + + + + + -V: Enable VBR and set a quality level from -50 to 50 (default is disbaled). + + The higher the number the better the quality. Maximum range is -50 to 50 but useful range is -10 to 10. See vbr documentation file for details. + If a value outside the range or the is set to , this property is not evaluated! + Using for example "-V -5" will force the encoder to favour the lower bitrate. Whereas using "-V 5" will force the encoder to favour the upper bitrate. + The value can actually be any integer. The larger the number, the greater the bitrate bias. + + + + + -P: The psychoacoustic model (PAM) TwoLAME should use (-1 to 4). + + Choose the psycho-acoustic model to use (-1 to 4). Model number -1 turns off psycho-acoustic modelling and uses fixed default values instead. + + + + -l: Set the ATH level. Default level is 0.0 (which will not use the property). + + ATH means Absolute Thresholds of Hearing. The ATH value raises/lowers the ATH by this many dB. + + + + -q: Enable quick mode (if value is geater than 0 (zero)). Only re-calculate psycho-acoustic model every specified number of frames (default is 0). + + + + + -c: Turn on Copyright flag in output bitstream (default is ). + + + + + -o: Turn off Original flag in output bitstream (default is ). + + + + + -p: Enable CRC error protection in output bitstream. An extra 16-bit checksum is added to each frame (default is ). + + + + + -d: Turn on padding in output bitstream (default is ). + + + + + -R: Reserve specified number of bits in the each from of the output bitstream (default is 0, which will not use this property). + + The value must be a multiple of 8 (e.g. 8, 16, 24, 32, ...). + + + + -e: Set the de-emphasis type (None, CCIT, 50/15ms). Default is None. + + + + + -E: Turn on energy level extensions (default is ). + + + + + This property return , if the file "twolame.exe" exists in the - else is returned. + + + + + Gets a value indicating the type of content. Here BASS_CTYPE_STREAM_MP2 is always returned. + + + + + This return the default extension of an output file for this encoder (".mp2"). + + + + + TwoLAME implements STDOUT, so is always returned. + + TwoLAME support broadcast streaming. + + + + Gets the actual encoder command-line string (using all TWO_xxx properties). + + The encoder command-line is evaluating the and members + as well as the TWO_xxx settings. + + + + Returns the effective encoder bitrate (in kbps) of the output. + + + No matter if you are using CBR- or VBR-Mode (see ) the value will be used to return the effective bitrate value. + + + + + The general TwoLAME encoding mode (stereo, joint stereo, mono etc.). + + + + + Default is JointStereo or Stereo depending on bitrate. + + + + + Stereo + + + + + Force LR stereo on all frames + + + + + Force dual channel all frames + + + + + Mono + + + + + The psychoacoustic model TwoLAME should use (-1 to 4, default is 3). + + + + + Default model will be selected by encoder. + + + + + Psychoacoustic Model: -1 (turns off psycho-acoustic modelling and uses fixed default values instead) + + This PAM doesn't actually look at the samples being encoded to decide upon the output values. There is simply a set of 32 default values which are used, regardless of input. + Pros: Faaaast. Low complexity. Surprisingly good. "Surprising" in that the other PAMs go to the effort of calculating FFTs and subbands and masking, and this one does absolutely nothing. Zip. Nada. Diddly Squat. This model might be the best example of why it is hard to make a good model - if having no computations sounds OK, how do you improve on it? + Cons: Absolutely no attempt to consider any of the masking effects that would help the audio sound better. + + + + + Psychoacoustic Model: 0 + + This PAM looks at the sizes of the scalefactors for the audio and combines it with the Absolute Threshold of Hearing (ATH) to make the 32 SMR values. + Pros: Faaast. Low complexity. + Cons: This model has absolutely no mathematical basis and does not use any perceptual model of hearing. It simply juggles some of the numbers of the input sound to determine the values. + + + + + Psychoacoustic Model: 1 + + This PAM is from the ISO standard. Just because they are the standard, doesn't mean that they are any good. Look at LAME which basically threw out the MP3 standard psycho models and made their own (GPSYCHO). + Pros: A reference for future PAMs. + Cons: Terrible ISO code, buggy tables, poor documentation. + + + + + Psychoacoustic Model: 2 + + This PAM is from the ISO standard. Just because they are the standard, doesn't mean that they are any good. Look at LAME which basically threw out the MP3 standard psycho models and made their own (GPSYCHO). + Pros: A reference for future PAMs. + Cons: Terrible ISO code, buggy tables, poor documentation. + + + + + Psychoacoustic Model: 3 + + A re-implementation of psychoacoustic model 1. ISO11172 was used as the guide for re-writing this PAM from the ground up. + Pros: No more obscure tables of values from the ISO code. Hopefully a good base to work upon for tweaking PAMs. + Cons: At the moment, doesn't really sound any better than PAM1. + + + + + Psychoacoustic Model: 4 + + A cleaned up version of PAM2. + Pros: Faster than PAM2. No more obscure tables of values from the ISO standard. Hopefully a good base to work from for improving the PAMs. + Cons: Still has the same "warbling"/"Davros" problems as PAM2. + + + + + The general TwoLAME encoding mode (stereo, joint stereo, mono etc.). + + + + + No Emphasis + + + + + Emphasis according to CCIT J.17 + + + + + Emphasis 50/15 ms + + + + + Encoder class implementation for AAC encoding using faac.exe. + + This class uses the encoder type. + FAAC (faac.exe) must be downloaded separately (e.g. from www.rarewares.org). + Make sure to set the FAAC_xxx flags before retrieving the or calling . + This implementation uses the automatic DSP system for encoding. + Meaning the sending of sample data to the encoder is done automatically when you play the channel () or call (if it's a decoding channel). + So there is no need to call manually! + + If you simply want to encode a physical file please also take a look to the . + + + + + Creates an instance of a FAAC encoder implementation. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + FAAC implements AAC encoding (BASS_CTYPE_STREAM_AAC). + + + + Returns the name of the Encoder. + + Returns "FAAC Encoder (BASS_CTYPE_STREAM_AAC)". + + + + This method starts the actual FAAC encoder. + + Optional callback function to receive the encoded data... = no callback. + To have the encoded data received by a callback function, the encoder needs to be told to output to STDOUT (instead of a file), so must return true. + User instance data to pass to the callback function. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Returns , if the encoder was successfully started - else is returned. + This method calls internally using the . + After the encoder was started successfully the returns a valid HENCODE handle. + If the encoder was not started successfully or was stopped returns 0 (zero). + This implementation starts the encoder with the BASS_ENCODE_NOHEAD flag. + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Converts a quality setting (between 10 and 500) to an approx. bitrate (in kbps). + + The FACC quality level to convert (between 10 and 500). + The rounded approximate bitrate in kbps. + + + + Use the parameter string only (default=). + + Caution: If set to no other FAAC_xxx options will be evaluated and ONLY the parameter string will be used! + + + + The custom parameter string, which should be used, if the property is set to . + + This property string will be appended to all other FAAC_xxx options, if the property is set to (default). + + + + Gets or Sets, if the Quality mode () will be used (default is ). + + + When using the Quality-Mode ( is set to ) you only specify a quality factor via and the bitrate parameter () is ignored. + When you turn off Quality-Mode ( is set to , default) the bitrate parameter is evaluated and the parameter is ignored! + + + + + -q: Set default variable bitrate (VBR) quantizer quality in percent. + + Default: 100, averages at approx. 120 kbps VBR for a normal stereo input file with 16 bit and 44.1 kHz sample rate. + Max. value is 500, Min. value is 10. + + + + -b: Set average bitrate (ABR) to approximately bitrate in kbps. + Max. value is 152 kbps/stereo with a 16 kHz cutoff, can be raised with a higher -c setting). + + + + + -c: Set the bandwidth in Hz (default: -1 automatic, i.e. adapts maximum value to input sample rate). + + + + + -w: Wrap AAC data in MP4 container (default is , generating an .m4a output). + + Setting this property to will generate an AAC stream (TAGs are not supported with AAC). + + + + --tns: Enable coding of TNS, temporal noise shaping (default is ). + + + + + --no-midside: Don't use mid/side coding (default is ). + + + + + --mpeg-vers: Force AAC MPEG version 2 or 4 (-1 use default). + + + + + --obj-type: AAC object type. "LC" (Low Complexity, default), "Main" or "LTP" (Long Term Prediction). + + + + + --shortctl: Enforce block type (0 = both (default), 1 = no short; 2 = no long). + + + + + -r: Generate raw AAC bitstream (i.e. without any headers, default is ). + + Not advised! RAW AAC files are practically useless! + + + + This property return , if the file "lame.exe" exists in the - else is returned. + + + + + Gets a value indicating the type of content. Here BASS_CTYPE_STREAM_AAC is always returned. + + + + + This return the default extension of an output file for this encoder (".m4a"). + + + + + FAAC implements STDOUT, so is always returned. + + FAAC support boradcast streaming. + + + + Gets the actual encoder command-line string (using all FAAC_xxx properties). + + The encoder command-line is evaluating the and members + as well as the FAAC_xxx settings. + + + + Returns the effective encoder bitrate (in kbps) of the output. + + + When using the Quality-Mode ( is set to , default) you only need to specify a quality factor via and the bitrate parameters is ignored. + In this case the effective bitrate will be calculated automatically according to the FAAC specification. + When you turn off Quality-Mode ( is set to ) the bitrate parameters is evaluated! + + + + + Encoder class implementation for FLAC encoding using "flac.exe". + + This class uses the encoder type. + "flac.exe" must be downloaded separately (e.g. from www.rarewares.org). FLAC also needs the "libmmd.dll", which is also available at rarewares.org. + Make sure to set the FLAC_xxx flags before retrieving the or calling . + This implementation uses the automatic DSP system for encoding. + Meaning the sending of sample data to the encoder is done automatically when you play the channel () or call (if it's a decoding channel). + So there is no need to call manually! + + If you simply want to encode a physical file please also take a look to the . + FLAC 'cuesheets' and the 'skip' and 'until' properties are not supported in this implementation by default, but you might add them with the parameter. + + + + + Creates an instance of a FLAC encoder implementation. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + Implements FLAC encoding (BASS_CTYPE_STREAM_FLAC). + + + + Returns the name of the Encoder. + + Returns "FLAC Encoder (.flac)" or "FLAC Encoder (.ogg)" depending on . + + + + This method starts the actual FLAC encoder. + After the encoder was started successfully the returns a valid HENCODE handle. + + Optional callback function to receive the encoded data... = no callback. + To have the encoded data received by a callback function, the encoder needs to be told to output to STDOUT (instead of a file), so must return true. + User instance data to pass to the callback function. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Returns , if the encoder was successfully started - else is returned. + This method calls internally using the . + After the encoder was started successfully the returns a valid HENCODE handle. + If the encoder was not started successfully or was stopped returns 0 (zero). + This implementation starts the encoder with the BASS_ENCODE_NOHEAD and if using 32-bit float input with the BASS_ENCODE_FP_24BIT flag. + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Use the parameter string only (default=). + + Caution: If set to no other FLAC_xxx options will be evaluated and ONLY the parameter string will be used! + + + + The custom parameter string, which should be used, if the property is set to . + + This property string will be appended to all other FLAC_xxx options, if the property is set to (default). + + + + --ogg: When encoding, generate Ogg FLAC output instead of native FLAC (default is ). + + Ogg FLAC streams are FLAC streams wrapped in an Ogg transport layer. + The resulting file should have an '.ogg' extension and will still be decodable by flac. + When setting this property to , the will be changed to ".ogg". + + + + + -V: Verify a correct encoding by decoding the output in parallel and comparing to the original (default is ). + + + + + --lax: Allow encoder to generate non-Subset files (default is ). + + + + + --replay-gain: Calculate ReplayGain values and store in Vorbis comments (default is ). + + Title gains/peaks will be computed for each file. + NOTE: this option may also leave a few extra bytes in the PADDING block. + + + + + -P: Tell the encoder to write a PADDING metadata block of the given length (in bytes) after the STREAMINFO block (default is off). + + This is useful if you plan to tag the file later with an APPLICATION block; instead of having to rewrite the entire file later just to insert your block, you can write directly over the PADDING block. + Note that the total length of the PADDING block will be 4 bytes longer than the length given, because of the 4 metadata block header bytes. + You can force no PADDING block at all to be written with "--no-padding". + The encoder writes a PADDING block of 4096 bytes by default. + If you set to , this option will have no effect. + + + + + --no-padding: Suppress writing a PADDING block of 4096 bytes (default is ). + + + + + -b: Specify the blocksize in samples (the default is 1152 for -l 0, else 4608). + + This must be one of 192, 576, 1152, 2304, 4608, 256, 512, 1024, 2048, 4096, 8192, 16384, or 32768 (unless "--lax" is used). + + + + + -0..-8: Defines the compression level (default is 5) between 0 (fast) and 8 (best). + + Although FLAC is a lossless format you can adjust the compression level. + A higher compression level (max. is 8) means a smaller output, whereas a lower compression level (min. is 0) means faster results. + + + + This property return , if the file "flac.exe" exists in the - else is returned. + + + + + Gets a value indicating the type of content. Here BASS_CTYPE_STREAM_FLAC is returned + (or BASS_CTYPE_STREAM_FLAC_OGG if is set to to ). + + + + + This return the default extension of an output file for this encoder (".flac"). + + If you set the option to this will return ".ogg" instead. + + + + FLAC implements STDOUT, so is always returned. + + FLAC support boradcast streaming. + + + + Gets the actual encoder command-line string (using all FLAC_xxx properties). + + The encoder command-line is evaluating the and members + as well as the FLAC_xxx settings. + + + + Returns the effective encoder bitrate (in kbps) of the output. + + + Since FLAC is a lossless format, no matter what compression mode you are using, the bitrate will always be taken from the raw input format. + Meaning the original , and the will be evaluated in order to calculate the effective bitrate. + + + + + Encoder class implementation for WavPack encoding using "wavpack.exe". + + This class uses the encoder type. + "wavpack.exe" must be downloaded separately (e.g. from www.wavpack.com or www.rarewares.org). + Make sure to set the WV_xxx flags before retrieving the or calling . + This implementation uses the automatic DSP system for encoding. + Meaning the sending of sample data to the encoder is done automatically when you play the channel () or call (if it's a decoding channel). + So there is no need to call manually! + + If you simply want to encode a physical file please also take a look to the . + + + + + Creates an instance of a WavPack encoder implementation. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + Implements WavPack encoding (BASS_CTYPE_STREAM_WV). + + + + Returns the name of the Encoder. + + Returns "WavPack Encoder (BASS_CTYPE_STREAM_WV)". + + + + This method starts the actual WavPack encoder. + After the encoder was started successfully the returns a valid HENCODE handle. + + Optional callback function to receive the encoded data... = no callback. + To have the encoded data received by a callback function, the encoder needs to be told to output to STDOUT (instead of a file), so must return true. + User instance data to pass to the callback function. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Returns , if the encoder was successfully started - else is returned. + This method calls internally using the . + After the encoder was started successfully the returns a valid HENCODE handle. + If the encoder was not started successfully or was stopped returns 0 (zero). + This implementation starts the encoder with no flags, meaning a Wave header will be send to the encoder to specify the bitrate, number of channels and samplerate (8, 16 and 32 bit are supported). + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Use the parameter string only (default=). + + Caution: If set to no other WV_xxx options will be evaluated and ONLY the parameter string will be used! + + + + The custom parameter string, which should be used, if the property is set to . + + This property string will be appended to all other WV_xxx options, if the property is set to (default). + + + + Enable hybrid compression? (default is ) + + When set to , the property is used. + If set to (default) WavPack is pure lossless, which means that the .wv file contains all the information that was in the original .wav file. + + + + -b: Hybrid compression, 24 - 9600 kbits/second (default is 1024 kbps). + + Only used, if is set to . + + + + -c: Create correction file (.wvc) for hybrid mode (=lossless, default is ) + + Only used, if is set to . + + + + -cc: Maximum hybrid compression (hurts lossy quality and decode speed, default is ). + + Only used, if is set to . + + + + -f: Fast mode (fast, but some compromise in compression ratio, default is ). + + + + + -h: High quality (best compression in all modes, but slower, default is ). + + + + + -i: Ignore length in wav header (no pipe output allowed, default is ). + + Sometimes If the length in the wav headers that is provided is not correct. + In this case use this option to force WavPack to ignore the header and accept the actual length. + Because WavPack must seek to the beginning of the output file to write the correct length, this option cannot be used with piped output. + + + + + -j0: Joint-stereo override ( = left/right, = mid/side, default is ). + + WavPack normally defaults to joint stereo (sometimes called mid/side) in which the left and right channels are combined to form an alternate representation (essentially L+R and L-R) that compresses better in lossless mode and improves quality in lossy mode. + This option allows this feature to be forced either on or off. + + + + + -l: Run at low priority (for smoother multitasking, default is ). + + + + + -m: Compute and store MD5 signature of raw audio data (default is ). + + + + + -n: Calculate average and peak quantization noise (hybrid only, default is ). + + Only used, if is set to . + This causes WavPack to calculate the average and peak quantization noise generated in the lossy version of the hybrid mode, both referenced in decibels below full scale. + While it is impossible to use this as a guide to determine the audibility of the noise, it is useful for comparing the various compression options and for comparing WavPack's lossy performance to other programs. + Note that this option does not currently produce meaningfull results for floating point or multichannels files. + + + + + -p = practical float storage (also 32-bit ints, not lossless, default is ). + + This option reduces the storage of some floating-point data files by up to about 10% by eliminating some information that has virtually no effect on the audio data. + While this does technically make the compression lossy, it retains all the advantages of floating point data (>600 dB of dynamic range, no clipping, and 25 bits of resolution). + This also affects large integer compression by limiting the resolution to 24 bits. + + + + + -r: Generate new RIFF wav header (removing extra chunk info, default is ). + + WavPack normally saves all the RIFF header information contained in the wav file (including any chunks after the audio data). + This is done so that WvUnpack.exe can restore the original wav files exactly. The -r option causes WavPack to discard the header contained in the source file (and any extra chunks) and generate a fresh wav header. + Obviously the source wav header is still used to determine the format and size of the file (i.e. this is not a "raw" mode). + Note that for multichannel files a WAVEFORMATEXTENSIBLE header is generated whether the source file had one or not. + + + + + -s: noise shaping override (hybrid only, -1.0 to 1.0, 0.0 = off = default) + + Only used, if is set to . + WavPack uses first-order noise shaping to improve the perceived quality of lossy files and to improve the hybrid lossless compression ratio. + Normally WavPack will choose the noise shaping most appropriate for the application, but this option allows the user to override the default. The parameter range is +/- 1.0, where positive values shift the noise higher in frequency and negative values shift the noise lower in frequency. Values very close to -1.0 are clipped to prevent problems associated with very high gain near DC + + + + + -t: Copy input file's time stamp to output file (default is ). + + Can only be used, if a is specified. + + + + -x: Extra encode processing (optional n = 1-6 for more/less, 0 = default). + + + Like previous versions of WavPack (and many other compressors), WavPack 4.31 normally works "symmetrically" in that encoding and decoding operate at about the same rate (regardless of the mode used). + However, WavPack now has an option to work "asymmetrically", so that extra processing can be done during encoding to provide better compression, but with NO corresponding cost to decoding performance! + This is enabled with the -x option and provides an average improvement in CD music compression of about 1% in "fast" mode, about 0.5% in the normal mode, and about 0.25% in "high" mode. + Because the standard compression parameters are optimized for "normal" CD music audio, this option works best with "non-standard" audio (synthesized sounds, non-standard sampling rates, etc) where it can often achieve enormous gains. + It should be noted that this mode is not just a little slower than the regular mode - it is MUCH slower. + However, the fact that it has no effect on decode time could make it attractive in some situations. + The "extra" option provides a level of extra processing that has been optimized for the encoding mode selected (i.e. normal, "fast" or "high"). + This level can be overridden with the optional numeric parameter from 1 to 6, although this is not generally recommended. + + + + + This property return , if the file "wavpack.exe" exists in the - else is returned. + + + + + Gets a value indicating the type of content. Here BASS_CTYPE_STREAM_WV is always returned. + + + + + This return the default extension of an output file for this encoder (".wv"). + + + + + WavPack does implement STDOUT, so is always returned. + + WavPack does support boradcast streaming. + + + + Gets the actual encoder command-line string (using all WV_xxx properties). + + The encoder command-line is evaluating the and members + as well as the WV_xxx settings. + + + + Returns the effective encoder bitrate (in kbps) of the output. + + + Since WavPack can be used as a hybrid lossy or fully lossless encoder, the will be used to determine the bitrate in kbps. + If the is set to (lossy), the bitrate is directly taken from the property. + If the is set to (lossless), the the original , and the will be evaluated in order to calculate the effective bitrate. + + + + + Encoder class implementation for MusePack MPC encoding using "mppenc.exe" resp. "mpcenc.exe". + + This class uses the encoder type. + "mppenc.exe" or "mpcenc.exe" must be downloaded separately (e.g. from www.musepack.net). + Note: "mpcenc.exe" is the default MusePack Stream Version 8 encoder. "mppenc.exe" is the MusePack Stream Version 7 encoder. + Use the property, if you want to use "mppenc.exe". By default "mpcenc.exe" (Stream Version 8) will be used. + Make sure to set the MPC_xxx flags before retrieving the or calling . + This implementation uses the automatic DSP system for encoding. + Meaning the sending of sample data to the encoder is done automatically when you play the channel () or call (if it's a decoding channel). + So there is no need to call manually! + + If you simply want to encode a physical file please also take a look to the . + This implementation does not use all possible tweaking switches, since they are mostly not recommended ny MusePack and since the default settings are already pretty much optimized. + However, if you for what ever reason need to add you swicth, you can make use of the property. + + + + + Creates an instance of a MPC encoder implementation. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + Implements MusePack encoding (BASS_CTYPE_STREAM_MPC). + + + + Returns the name of the Encoder. + + Returns "MusePack Encoder (BASS_CTYPE_STREAM_MPC)". + + + + This method starts the actual MPC encoder. + After the encoder was started successfully the returns a valid HENCODE handle. + + Optional callback function to receive the encoded data... = no callback. + To have the encoded data received by a callback function, the encoder needs to be told to output to STDOUT (instead of a file), so must return true. + User instance data to pass to the callback function. + Start the encoder paused? If , you might use to unpause (and really start the encoder). + Returns , if the encoder was successfully started - else is returned. + This method calls internally using the . + After the encoder was started successfully the returns a valid HENCODE handle. + If the encoder was not started successfully or was stopped returns 0 (zero). + This implementation starts the encoder with the BASS_ENCODE_FP_32BIT flag (since no 32bit floating point are supported), this also means a Wave header will be send to the encoder to specify the bitrate, number of channels and samplerate (8, 16, 24 and 32 bit are supported). + If an encoder stops running prematurely, should still be called to release resources that were allocated for the encoding. + + + + + Returns the string representation of the current encoder settings. + + The descriptive settings string. + + + + Use "mppenc.exe" (Stream Version 7)? + + + By default "mpcenc.exe" (Stream Version 8) will be used. + Set this option to in order to use "mppenc.exe" (Stream Version 7). + + + + + Use the parameter string only (default=). + + Caution: If set to no other MPC_xxx options will be evaluated and ONLY the parameter string will be used! + + + + The custom parameter string, which should be used, if the property is set to . + + This property string will be appended to all other MPC_xxx options, if the property is set to (default). + + + + Quality preset (use one of the values, default is "standard"). + + + + + --scale: Scale input signal by x (default: 1.00000, no scaling). + + + + + --quality: Set Quality to x (default is 5, between 0 and 10). + + + + + --nmt: Set NMT value to x dB (default is 6.5). + + + + + --tmn: Set TMN value to x dB (default is 18.0). + + + + + --pns: Set PNS value to x dB (default is 0.0). + + + + + This property return , if the file "mppenc.exe" exists in the - else is returned. + + + + + Gets a value indicating the type of content. Here BASS_CTYPE_STREAM_MPC is always returned. + + + + + This return the default extension of an output file for this encoder (".mpc"). + + + + + MusePack does implement STDOUT, so is always returned. + + MusePack does support boradcast streaming. + + + + Gets the actual encoder command-line string (using all MPC_xxx properties). + + The encoder command-line is evaluating the and members + as well as the MPC_xxx settings. + + + + + Returns the effective encoder bitrate (in kbps) of the output. + + + Since MusePack uses presets the appropriate bitrate associated with the will be returned in any case. + + + + + Profile options, Quality preset. To be used with . + + + + + lowest quality (typ. 60 kbps) + + + + + low quality/internet (typ. 90 kbps) + + + + + medium (MP3) quality (typ. 130 kbps) + + + + + high quality (default) (typ. 180 kbps) + + + + + extreme high quality (typ. 210 kbps) + + + + + extreme high quality (typ. 240 kbps) + + + + + extreme high quality (typ. 270 kbps) + + + + + Bass.Net registration class. + Used to register your BASS.NET API license and to optionally supress the splash screen. + + Not needed when using the freeware version of BASS.NET. + When you purchased a valid license for BASS.NET you will obtain a 'Registration-Key' together with your 'eMail'. + Call the method prior to any other BASS method with these 2 parameters in order to suppress the BASS.NET freeware splash screen. + If you like to support BASS.NET anyhow, you might call the method manually. + + + Register BASS.NET: + + BassNet.Registration("your emai", "your registration code"); + ... + Bass.Init(...); + + Register BASS.NET, but show splash anyhow (for 30sec., center parent, 5% transparent): + + BassNet.Registration("your email", "your registration code"); + BassNet.ShowSplash(this, 30000, 0.95, 2); + ... + Bass.Init(...); + + + BassNet.Registration("your email", "your registration code") + BassNet.ShowSplash(Me, 30000, 0.95, 2) + ... + Bass.Init(...) + + + + + + NOT needed - all members are static. + + + + + Base static contructor. + + + + + Gets or Sets, if the version check should be omitted when initializing Bass, BassWaspi or BassAsio. + + + By default a version check is performed whenever Bass, BassWaspi or BassAsio is initialized. + However, this automatic version check might sometimes not be desired, + in such case you might want to set this property to . + + + + + Registers your BASS.NET version and suppresses the freeware splash screen. + + Your eMail address for which you obtained a license. + The Registration-Key as obtained with the license. + IMPORTANT: Make sure to call this method prior to any other BASS method! + + + + Shows the splash screen, even if you have registered BASS.NET. + + The owner of the splash screen (or ). + The number of milliseconds to show the splash screen (use -1 to show infinit until the uses closes the splash or pressed ESC). + The opacity of the splash screen (1.0 = no opacity, 0.0 = fully transparent). + Defines where the splash screen should be shown: + 0 = CenterScreen + 1 = WindowsDefaultLocation + 2 = CenterParent + + + Register BASS.NET, but show splash anyhow (for 30sec., center parent, 5% transparent): + + BassNet.Registration("your email", "your registration code"); + BassNet.ShowSplash(this, 30000, 0.95, 2); + ... + Bass.Init(...); + + Show splash (infinit until closed, center screen): + + BassNet.Registration("your email", "your registration code"); + BassNet.ShowSplash(null, -1, 1.0, 0); + ... + Bass.Init(...); + + + + + + Shows a BASS.NET about dialog. + + The owner of the modal about dialog (or ). + + + + Gets the internal name, which the productname and version. + + + + + Gets or Sets whether or not to use a broken behavior for Latin-1 strings (e.g. common to ID3v1 and ID3v2 tags). + + + if the broken behavior is to be used. Otherwise, . + + Many media players and taggers incorrectly treat Latin-1 fields as "default encoding" fields. As such, a + tag may end up with Windows-1250 resp. Windows-1252 encoded text. + While this problem would be apparent when moving a file from one computer to another, it would not be apparent on the original machine. + By setting this property to , your program will behave like Windows Media Player and others, + who read tags with this broken behavior. + + + + + Gets or Sets whether or not to use UTF-8 strings when reading RIFF INFO (LIST INFO) chunks. + + + if UTF-8 is to be used. Otherwise, . + + Some media players and taggers incorrectly use UTF-8 strings for RIFF INFO (LIST INFO) chunks instead of "Latin1". + By setting this property to , your program will read any RIFF INFO (LIST INFO) chunks as UTF-8 strings. + + + + + BASS.NET API wrapper for BASS.DLL + Requires: bass.dll - Bass Audio Library - available @ www.un4seen.com. + + + BASS is an audio library for use in Windows and MacOSX software. It's purpose is to provide the most powerful and efficient (yet easy to use), + sample, stream, MOD music, and recording functions. All in a tiny DLL, under 100KB in size. + BASS requires DirectX 3 or above for output. BASS does not require that a soundcard with DirectSound/DirectSound3D hardware accelerated drivers is + installed, but it does improve performance if there is one. BASS also takes advantage of MMX, which improves the performance of the MOD music playback + There is no guarantee that all future BASS versions will be compatible with all previous versions, so your program should use to check the version that is loaded. + This also means that you should put the BASS module in the same directory as your executable (not just somewhere in the path), to avoid the possibility of a wrong version being loaded. + There is no need to create an instance of this class, since all Bass methods are declared as static. + + My first BASS application: + + using System; + using Un4seen.Bass; + + namespace MyFirstBass + { + class Program + { + static void Main(string[] args) + { + // init BASS using the default output device + if ( Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) ) + { + // create a stream channel from a file + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_DEFAULT); + if (stream != 0) + { + // play the stream channel + Bass.BASS_ChannelPlay(stream, false); + } + else + { + // error creating the stream + Console.WriteLine("Stream error: {0}", Bass.BASS_ErrorGetCode()); + } + + // wait for a key + Console.WriteLine("Press any key to exit"); + Console.ReadKey(false); + + // free the stream + Bass.BASS_StreamFree(stream); + // free BASS + Bass.BASS_Free(); + } + } + } + } + + + Imports System + Imports Un4seen.Bass + + Namespace MyFirstBass + Class Program + Shared Sub Main(ByVal args() As String) + ' init BASS using the default output device + If Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) Then + ' create a stream channel from a file + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0L, 0L, BASSFlag.BASS_DEFAULT) + If stream <> 0 Then + ' play the stream channel + Bass.BASS_ChannelPlay(stream, False) + Else + ' error creating the stream + Console.WriteLine("Stream error: {0}", Bass.BASS_ErrorGetCode()) + End If + + ' wait for a key + Console.WriteLine("Press any key to exit") + Console.ReadKey(False) + + ' free the stream + Bass.BASS_StreamFree(stream) + ' free BASS + Bass.BASS_Free() + End If + End Sub + End Class + End Namespace + + + + + + Current BASS version (without minor revision). + + + + + The BASS way to say = 0. + + + + + The BASS way to say = 1. + + + + + The BASS way to say ERROR = -1. + + + + + Base static contructor. + + + + + + + + + + + + + + + + Initializes an output device. + + The device to use... -1 = default device, 0 = no sound, 1 = first real output device. + or can be used to get the total number of devices. + + Output sample rate. + Any combination of these flags (see ): + + BASS_DEVICE_8BITSUse 8-bit resolution, else 16-bit. + BASS_DEVICE_MONOUse mono, else stereo. + BASS_DEVICE_3DEnable 3D functionality. If this flag is not specified, then the BASS_SAMPLE_3D flag is ignored when loading/creating a sample/stream/music. + BASS_DEVICE_LATENCYCalculates the latency of the device, that is the delay between requesting a sound to play and it acually being heard. A recommended minimum buffer length is also calculated. Both values are retrievable in the BASS_INFO structure (latency and minbuf members). These calculations can increase the time taken by this function by 1-3 seconds. + BASS_DEVICE_SPEAKERSForce the enabling of speaker assignment. With some devices/drivers, the number of speakers BASS detects may be 2, when the device in fact supports more than 2 speakers. This flag forces the enabling of assignment to all 8 possible speakers. This flag has no effect with non-WDM drivers. + BASS_DEVICE_CPSPEAKERUse the Windows control panel setting to detect the number of speakers. Soundcards generally have their own control panel to set the speaker config, so the Windows control panel setting may not be accurate unless it matches that. This flag has no effect on Vista, as the speakers are already accurately detected. + BASS_DEVICE_NOSPEAKERIgnore speaker arrangement. This flag tells BASS not to make any special consideration for speaker arrangements when using the SPEAKER flags, eg. swapping the CENLFE and REAR speaker channels in 5/7.1 speaker output. This flag should be used with plain multi-channel (rather than 5/7.1) devices. + BASS_DEVICE_DMIXLinux only: Initialize the device using the ALSA "dmix" plugin, else initialize the device for exclusive access. + BASS_DEVICE_FREQSet the device's output rate to , otherwise leave it as it is. + + + The application's main window... = the current foreground window (use this for console applications). + If the device was successfully initialized, is returned, else is returned. Use to get the error code. + + This function must be successfully called before using any sample, stream or MOD music functions. The recording functions may be used without having called this function. + Playback is not possible with the "no sound" device, but it does allow the use of "decoding channels", eg. to decode files. + Simultaneously using multiple devices is supported in the BASS API via a context switching system - instead of there being an extra "device" parameter in the function calls, the device to be used is set prior to calling the functions. is used to switch the current device. When successful, BASS_Init automatically sets the current thread's device to the one that was just initialized. + When using the default device (device = -1), can be used to find out which device it was mapped to. On Windows, it'll always be the first device. + + + ERROR CODEDescription + BASS_ERROR_DXDirectX (or ALSA) is not installed. + BASS_ERROR_DEVICEThe device number specified is invalid. + BASS_ERROR_ALREADYThe device has already been initialized. You must call before you can initialize it again. + BASS_ERROR_DRIVERThere is no available device driver... the device may already be in use. + BASS_ERROR_FORMATThe specified format is not supported by the device. Try changing the and parameters. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DThe device has no 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + On Linux, a 'Default' device is hardcoded to device number 1, which uses the default output set in the ALSA config; that could map directly to one of the other devices or it could use ALSA plugins. If the config option has been enbled, a "Default" device is also available on Windows, who's output will follow default device changes on Windows 7. In both cases, the "Default" device will also be the default device (device = -1). + The sample format specified in the and parameters has no effect on the device output on iOS or OSX, and not on Windows unless VxD drivers are used (on Windows 98/95); with WDM drivers (on Windows XP/2000/Me/98SE), the output format is automatically set depending on the format of what is played and what the device supports, while on Vista and above, the output format is determined by the user's choice in the Sound control panel. On Linux the output device will use the specified format if possible, but will otherwise use a format as close to it as possible. If the BASS_DEVICE_FREQ flag is specified on iOS or OSX, then the device's output rate will be set to the freq parameter (if possible). The BASS_DEVICE_FREQ flag has no effect on other platforms. can be used to check what the output format actually is. + The parameter is only used on Windows and are ignored on other platforms. That applies to the BASS_DEVICE_CPSPEAKERS and BASS_DEVICE_SPEAKERS flags too, as the number of available speakers is always accurately detected on the other platforms. The BASS_DEVICE_LATENCY flag is also ignored on Linux/OSX/Android/Windows CE, as latency information is available without it. The latency is also available without it on iOS, but not immediately following this function call unless the flag is used. + The BASS_DEVICE_DMIX flag is only available on Linux, and allows multiple applications to share the device (if they all use 'dmix'). It may also be possible for multiple applications to use exclusive access if the device is capable of hardware mixing. If exclusive access initialization fails, the BASS_DEVICE_DMIX flag will automatically be tried; if that happens, it can be detected via and the initflags. + On Linux and Windows CE, the length of the device's buffer can be set via the config option. + + + Initialize BASS with the current form window handle: + + Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, this.Handle); + + + Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, Me.Handle) + + + + + + + + + + + + + + + + + Initializes an output device. + + The device to use... -1 = default device, 0 = no sound, 1 = first real output device. + or can be used to get the total number of devices. + + Output sample rate. + Any combination of these flags (see ): + + BASS_DEVICE_8BITSUse 8-bit resolution, else 16-bit. + BASS_DEVICE_MONOUse mono, else stereo. + BASS_DEVICE_3DEnable 3D functionality. If this flag is not specified, then the BASS_SAMPLE_3D flag is ignored when loading/creating a sample/stream/music. + BASS_DEVICE_LATENCYCalculates the latency of the device, that is the delay between requesting a sound to play and it acually being heard. A recommended minimum buffer length is also calculated. Both values are retrievable in the BASS_INFO structure (latency and minbuf members). These calculations can increase the time taken by this function by 1-3 seconds. + BASS_DEVICE_SPEAKERSForce the enabling of speaker assignment. With some devices/drivers, the number of speakers BASS detects may be 2, when the device in fact supports more than 2 speakers. This flag forces the enabling of assignment to all 8 possible speakers. This flag has no effect with non-WDM drivers. + BASS_DEVICE_CPSPEAKERUse the Windows control panel setting to detect the number of speakers. Soundcards generally have their own control panel to set the speaker config, so the Windows control panel setting may not be accurate unless it matches that. This flag has no effect on Vista, as the speakers are already accurately detected. + BASS_DEVICE_NOSPEAKERIgnore speaker arrangement. This flag tells BASS not to make any special consideration for speaker arrangements when using the SPEAKER flags, eg. swapping the CENLFE and REAR speaker channels in 5/7.1 speaker output. This flag should be used with plain multi-channel (rather than 5/7.1) devices. + BASS_DEVICE_DMIXLinux only: Initialize the device using the ALSA "dmix" plugin, else initialize the device for exclusive access. + BASS_DEVICE_FREQSet the device's output rate to , otherwise leave it as it is. + + + The application's main window... = the current foreground window (use this for console applications). + Class identifier of the object to create, that will be used to initialize DirectSound... = use default + If the device was successfully initialized, is returned, else is returned. Use to get the error code. + + This function must be successfully called before using any sample, stream or MOD music functions. The recording functions may be used without having called this function. + Playback is not possible with the "no sound" device, but it does allow the use of "decoding channels", eg. to decode files. + When specifying a class identifier (clsid), after successful initialization, you can use to retrieve the DirectSound object, and through that access any special interfaces that the object may provide. + Simultaneously using multiple devices is supported in the BASS API via a context switching system - instead of there being an extra "device" parameter in the function calls, the device to be used is set prior to calling the functions. is used to switch the current device. When successful, BASS_Init automatically sets the current thread's device to the one that was just initialized. + When using the default device (device = -1), can be used to find out which device it was mapped to. On Windows, it'll always be the first device. + + + ERROR CODEDescription + BASS_ERROR_DEVICEThe device number specified is invalid. + BASS_ERROR_ALREADYThe device has already been initialized. You must call before you can initialize it again. + BASS_ERROR_DRIVERThere is no available device driver... the device may already be in use. + BASS_ERROR_FORMATThe specified format is not supported by the device. Try changing the and parameters. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DThe device has no 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + On Linux, a 'Default' device is hardcoded to device number 1, which uses the default output set in the ALSA config; that could map directly to one of the other devices or it could use ALSA plugins. If the config option has been enbled, a "Default" device is also available on Windows, who's output will follow default device changes on Windows 7. In both cases, the "Default" device will also be the default device (device = -1). + The sample format specified in the and parameters has no effect on the device output on iOS or OSX, and not on Windows unless VxD drivers are used (on Windows 98/95); with WDM drivers (on Windows XP/2000/Me/98SE), the output format is automatically set depending on the format of what is played and what the device supports, while on Vista and above, the output format is determined by the user's choice in the Sound control panel. On Linux the output device will use the specified format if possible, but will otherwise use a format as close to it as possible. If the BASS_DEVICE_FREQ flag is specified on iOS or OSX, then the device's output rate will be set to the freq parameter (if possible). The BASS_DEVICE_FREQ flag has no effect on other platforms. can be used to check what the output format actually is. + The and parameters are only used on Windows and are ignored on other platforms. That applies to the BASS_DEVICE_CPSPEAKERS and BASS_DEVICE_SPEAKERS flags too, as the number of available speakers is always accurately detected on the other platforms. The BASS_DEVICE_LATENCY flag is also ignored on Linux/OSX/Android/Windows CE, as latency information is available without it. The latency is also available without it on iOS, but not immediately following this function call unless the flag is used. + The BASS_DEVICE_DMIX flag is only available on Linux, and allows multiple applications to share the device (if they all use 'dmix'). It may also be possible for multiple applications to use exclusive access if the device is capable of hardware mixing. If exclusive access initialization fails, the BASS_DEVICE_DMIX flag will automatically be tried; if that happens, it can be detected via and the initflags. + On Linux and Windows CE, the length of the device's buffer can be set via the config option. + + + Initialize BASS with the current form window handle: + + Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, this.Handle); + + + Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, Me.Handle) + + Initialize BASS/DirectSound with A3D + + Guid clsidA3d = new Guid(0xd8f1eee0, 0xf634, 0x11cf, 0x87, 0x0, 0x0, 0xa0, 0x24, 0x5d, 0x91, 0x8b); + Bass.BASS_Init(-1, 44100, 0, this.Handle, clsidA3d); + + + Dim clsidA3d As Guid = New Guid(0xd8f1eee0, 0xf634, 0x11cf, 0x87, 0x0, 0x0, 0xa0, 0x24, 0x5d, 0x91, 0x8b) + Bass.BASS_Init(-1, 44100, 0, Me.Handle, clsidA3d) + + + + + + + + + + + + + + Retrieves information on an output device. + + The device to get the information of... 0 = first. + An instance of the class to store the information at. + If successful, then is returned, else is returned. Use to get the error code. + + This function can be used to enumerate the available devices for a setup dialog. + Device 0 is always the "no sound" device, so if you should start at device 1 if you only want to list real devices. + + + ERROR CODEDescription + BASS_ERROR_DEVICEThe device number specified is invalid. + + + Platform-specific + On Linux, a "Default" device is hardcoded to device number 1, which uses the default output set in the ALSA config, and the real devices start at number 2. + + + List all available devices: + + BASS_DEVICEINFO info = new BASS_DEVICEINFO(); + for (int n=0; Bass.BASS_GetDeviceInfo(n, info); n++) + { + Console.WriteLine(info.ToString()); + } + + + Dim n As Integer = 0 + Dim info As New BASS_DEVICEINFO() + While (Bass.BASS_GetDeviceInfo(n, info)) + Console.WriteLine(info.ToString()) + n += 1 + End While + + Or use the method for more convenience. + + + + + Retrieves information on an output device. + + The device to get the information of... 0 = first. + If successful, then an instance of the class is returned, else is returned. Use to get the error code. + + This function can be used to enumerate the available devices for a setup dialog. + Device 0 is always the "no sound" device, so if you should start at device 1 if you only want to list real devices. + + + ERROR CODEDescription + BASS_ERROR_DEVICEThe device number specified is invalid. + + + Platform-specific + On Linux, a "Default" device is hardcoded to device number 1, which uses the default output set in the ALSA config, and the real devices start at number 2. + + Find the system default device: + + int defDevice = -1; + BASS_DEVICEINFO info; + for (int n = 0; (info = Bass.BASS_GetDeviceInfo(n)) != null; n++) + { + if (info.IsDefault) + { + defDevice = n; + break; + } + } + + + Dim defDevice As Integer = -1 + Dim n As Integer = 0 + Dim info As New BASS_DEVICEINFO() + While Not (info Is Nothing) + info = Bass.BASS_GetDeviceDescription(n) + If Not (info Is Nothing) And info.IsDefault Then + defDevice = n + Exit While + End If + n += 1 + End While + + Or use the method for more convenience. + + + + + Returns all available output devices. + + An array of elements representing the available output devices. + Uses internally. + + + + Returns the total number of available output devices. + + Number of real output devices available. + Uses internally. + + + + Retrieves information on the device being used. + + An instance of the class to store the information at. + If successful, is returned, else is returned. Use to get the error code. + + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + + + + + + if ( Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, this.Handle) ) + { + BASS_INFO info = new BASS_INFO(); + if (Bass.BASS_GetInfo(info)) + Console.WriteLine( info.ToString() ); + } + + + If Bass.BASS_Init(- 1, 44100, BASSInit.BASS_DEVICE_DEFAULT, Me.Handle) Then + Dim info As New BASS_INFO() + If Bass.BASS_GetInfo(info) Then + Console.WriteLine(info.ToString()) + End If + End If + + + + + + Retrieves information on the device being used. + + An instance of the class on success - or on error. + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + + + + + Check if the current device has DirectSound support: + + if ( Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, this.Handle) ) + { + BASS_INFO info = Bass.BASS_GetInfo(); + if (info != null && !info.SupportsDirectSound) + Console.WriteLine("Device does NOT have DirectSound support"); + } + + + If Bass.BASS_Init(- 1, 44100, BASSInit.BASS_DEVICE_DEFAULT, Me.Handle) Then + Dim info As BASS_INFO = Bass.BASS_GetInfo() + If info IsNot Nothing AndAlso Not info.SupportsDirectSound Then + Console.WriteLine("Device does NOT have DirectSound support") + End If + End If + + + + + + Retrieves the error code for the most recent BASS function call in the current thread. + + If no error occured during the last BASS function call then BASS_OK is returned, else one of the values is returned. + See the function description for an explanation of what the error code means. + Error codes are stored for each thread. So if you happen to call 2 or more BASS functions at the same time, they will not interfere with eachother's error codes. + + + + Stops the output, stopping all musics/samples/streams. + + If successful, then is returned, else is returned. Use to get the error code. + + This function can be used after to stop the paused channels, so that they will not be resumed the next time is called. + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + + + + + + + Frees all resources used by the output device, including all it's samples, streams, and MOD musics. + + If successful, then is returned, else is returned. Use to get the error code. + + This function should be called for all initialized devices before your program exits. It's not necessary to individually free the samples/streams/musics as these are all automatically freed by this function. + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + + + + + + // init device 1 and 2 + Bass.BASS_Init(1, 44100, BASSInit.BASS_DEVICE_DEFAULT, this.Handle); + Bass.BASS_Init(2, 44100, BASSInit.BASS_DEVICE_DEFAULT, this.Handle); + ... + // create the stream for device 1 + Bass.BASS_SetDevice(1); + int stream = Bass.BASS_StreamCreateFile("afile.mp3", 0, 0, BASSFlag.BASS_DEFAULT); + ... + // create the stream for device 2 + Bass.BASS_SetDevice(2); + int stream = Bass.BASS_StreamCreateFile("afile.mp3", 0, 0, BASSFlag.BASS_DEFAULT); + ... + // free any initialized device + Bass.BASS_SetDevice(1); + Bass.BASS_Free(); + Bass.BASS_SetDevice(2); + Bass.BASS_Free(); + + + ' init device 1 and 2 + Bass.BASS_Init(1, 44100, BASSInit.BASS_DEVICE_DEFAULT, Me.Handle) + Bass.BASS_Init(2, 44100, BASSInit.BASS_DEVICE_DEFAULT, Me.Handle) + ... + ' create the stream for device 1 + Bass.BASS_SetDevice(1) + Dim stream As Integer = Bass.BASS_StreamCreateFile("afile.mp3", 0, 0, BASSFlag.BASS_DEFAULT) + ' create the stream for device 2 + Bass.BASS_SetDevice(2) + Dim stream As Integer = Bass.BASS_StreamCreateFile("afile.mp3", 0, 0, BASSFlag.BASS_DEFAULT) + ... + ' free any initialized device + Bass.BASS_SetDevice(1) + Bass.BASS_Free() + Bass.BASS_SetDevice(2) + Bass.BASS_Free() + + + + + + Retrieves the version number of the BASS.DLL that is loaded. + + The BASS version. For example, 0x02040103 (hex), would be version 2.4.1.3. + There is no guarantee that a previous or future version of BASS supports all the BASS functions that you are using, so you should always use this function to make sure the correct version is loaded. + It is safe to assume that future minor revisions (indicated in the LOWORD) will be fully compatible. + You might use the global constant to check the major revision. + + + Checking the major version only: + + if ( Utils.HighWord(Bass.BASS_GetVersion()) != Bass.BASSVERSION ) + { + MessageBox.Show(this, "Wrong Bass Version!"); + } + + + If Utils.HighWord(Bass.BASS_GetVersion()) <> Bass.BASSVERSION Then + MessageBox.Show(Me, "Wrong Bass Version!") + End If + + Checking for full version "2.4.1.3": + + if (Bass.BASS_GetVersion() < Utils.MakeLong(0x0103, 0x0204)) + { + MessageBox.Show(this, "Wrong Bass Version!"); + } + + + If Bass.BASS_GetVersion() < Utils.MakeLong(&H103, &H204) Then + MessageBox.Show(Me, "Wrong Bass Version!") + End If + + + + + + Retrieves the version of the BASS.DLL that is loaded. + + The number of components to use. The fieldCount ranges from 1 to 4 (major.minor.build.revision). + The BASS version (major.minor.build.revision). + There is no guarantee that a previous or future version of BASS supports all the BASS functions that you are using, so you should always use this function to make sure the correct version is loaded. + It is safe to assume that future minor revisions (indicated in the LOWORD) will be fully compatible. + + + Version expectedVersion = new Version(2, 4); + if (Bass.BASS_GetVersion(2) < expectedVersion) + { + MessageBox.Show( this, "Wrong Bass Version!" ); + } + + + Dim expectedVersion As New Version(2, 4) + If Bass.BASS_GetVersion(2) < expectedVersion Then + MessageBox.Show(Me, "Wrong Bass Version!") + End If + + + + + + Sets the device to use for subsequent calls in the current thread. + + The device to use... 0 = no sound, 1 = first real output device. + If successful, then is returned, else is returned. Use to get the error code. + + Simultaneously using multiple devices is supported in the BASS API via a context switching system - instead of there being an extra "device" parameter in the function calls, the device to be used is set prior to calling the functions. The device setting is local to the current thread, so calling functions with different devices simultaneously in multiple threads is not a problem. + The functions that use the device selection are the following: + , , , , , , , , , , , , , . + It also determines which device is used by a new sample/stream/music: , , , etc... + When one of the above functions (or ) is called, BASS will check the current thread's device setting, and if no device is selected (or the selected device is not initialized), BASS will automatically select the lowest device that is initialized. This means that when using a single device, there is no need to use this function; BASS will automatically use the device that is initialized. Even if you free the device, and initialize another, BASS will automatically switch to the one that is initialized. + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_INITThe device has not been initialized. + + + + + + // init device 1 and 2 + Bass.BASS_Init(1, 44100, BASSInit.BASS_DEVICE_DEFAULT, this.Handle); + // now device 1 is the current one + Bass.BASS_Init(2, 44100, BASSInit.BASS_DEVICE_DEFAULT, this.Handle); + // now device 2 is the current one + ... + // create the stream for device 1 + Bass.BASS_SetDevice(1); + // now device 1 is the current one + int stream = Bass.BASS_StreamCreateFile("afile.mp3", 0, 0, BASSFlag.BASS_DEFAULT); + ... + // create the stream for device 2 + Bass.BASS_SetDevice(2); + // now device 2 is the current one + int stream = Bass.BASS_StreamCreateFile("afile.mp3", 0, 0, BASSFlag.BASS_DEFAULT); + ... + // free any initialized device + Bass.BASS_SetDevice(1); + Bass.BASS_Free(); + Bass.BASS_SetDevice(2); + Bass.BASS_Free(); + + + ' init device 1 and 2 + Bass.BASS_Init(1, 44100, BASSInit.BASS_DEVICE_DEFAULT, Me.Handle) + ' now device 1 is the current one + Bass.BASS_Init(2, 44100, BASSInit.BASS_DEVICE_DEFAULT, Me.Handle) + ' now device 2 is the current one + ... + ' create the stream for device 1 + Bass.BASS_SetDevice(1) + ' now device 1 is the current one + Dim stream As Integer = Bass.BASS_StreamCreateFile("afile.mp3", 0, 0, BASSFlag.BASS_DEFAULT) + ' create the stream for device 2 + Bass.BASS_SetDevice(2) + ' now device 2 is the current one + Dim stream As Integer = Bass.BASS_StreamCreateFile("afile.mp3", 0, 0, BASSFlag.BASS_DEFAULT) + ... + ' free any initialized device + Bass.BASS_SetDevice(1) + Bass.BASS_Free() + Bass.BASS_SetDevice(2) + Bass.BASS_Free() + + + + + + Retrieves the device setting in the current thread. + + If successful, the device number is returned, else -1 is returned. Use to get the error code. + See also . + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called - there are no initialized devices. + + + + + + + Retrieves a pointer to a DirectSound object interface. + Not recommended to be used by managed applications! + + The interface to retrieve. + This can be a HMUSIC / HSTREAM / HCHANNEL handle, in which case an IDirectSoundBuffer interface is returned, or one of the following (see ): + + BASS_OBJECT_DSRetrieve the IDirectSound interface. + BASS_OBJECT_DS3DLRetrieve the IDirectSound3DListener interface. + + + If succesful, then a pointer to the requested object is returned, otherwise is returned. Use to get the error code. + + This function allows those that are familiar with DirectSound to access the internal DirectSound object interfaces, so that extra external functionality can be "plugged" into BASS. If you create any objects through a retrieved interface, make sure you release the objects before calling . + See the DirectX SDK for information on the DirectSound interfaces. + When using multiple devices, and requesting either the BASS_OBJECT_DS or BASS_OBJECT_DS3DL object interfaces, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_ILLPARAM is invalid. + BASS_ERROR_NOTAVAILThe requested object is not available with the current device. + + + + + + + Retrieves a pointer to a DirectSound object interface. + Not recommended to be used by managed applications! + + The interface to retrieve. + This can be a HMUSIC / HSTREAM / HCHANNEL handle, in which case an IDirectSoundBuffer interface is returned, or one of the following (see ): + + BASS_OBJECT_DSRetrieve the IDirectSound interface. + BASS_OBJECT_DS3DLRetrieve the IDirectSound3DListener interface. + + + If succesful, then a pointer to the requested object is returned, otherwise is returned. Use to get the error code. + + This function allows those that are familiar with DirectSound to access the internal DirectSound object interfaces, so that extra external functionality can be "plugged" into BASS. If you create any objects through a retrieved interface, make sure you release the objects before calling . + See the DirectX SDK for information on the DirectSound interfaces. + When using multiple devices, and requesting either the BASS_OBJECT_DS or BASS_OBJECT_DS3DL object interfaces, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_ILLPARAM is invalid. + BASS_ERROR_NOTAVAILThe requested object is not available with the current device. + + + Platform-specific + DirectSound in a Windows thing, so this function is not available on other platforms. + + + + + "Manually" updates the HSTREAM and HMUSIC channel buffers. + + The amount to render, in milliseconds. + If successful, then is returned, else is returned. Use to get the error code. + + When automatic updating is disabled, this function (or ) needs to be called to keep the playback buffers updated. + The length parameter should include some safety margin, in case the next update cycle gets delayed. + For example, if calling this function every 100ms, 200 would be a reasonable length parameter. + + + ERROR CODEDescription + BASS_ERROR_NOTAVAILUpdating is already in progress. + + + + + + + Retrieves the current CPU usage of BASS. + + The BASS CPU usage as a percentage of total CPU time. + + This function includes the time taken to render stream (HSTREAM) and MOD music (HMUSIC) channels during playback, and any DSP functions set on those channels. Also, any FX that are not using the "with FX flag" DX8 effect implementation. + The rendering of some add-on stream formats may not be entirely included, if they use additional decoding threads. See the add-on documentation for details. + This function does not strictly tell the CPU usage, but rather how timely the buffer updates are. For example, if it takes 10ms to render 100ms of data, that would be 10%. If the reported usage gets to 100%, that means the channel data is being played faster than it can be rendered, and buffer underruns are likely to occur. + If automatic updating is disabled, then the value returned by this function is only updated after each call to . usage is not included. + Platform-specific + On Windows, the CPU usage does not include sample channels (HCHANNEL), which are mixed by the output device/drivers (hardware mixing) or Windows (software mixing). On other platforms, the CPU usage does include sample playback as well as the generation of the final output mix. + + + + + Starts (or resumes) the output. + + If successful, then is returned, else is returned. Use to get the error code. + + The output is automatically started by , so there is no need to use this function unless you've stopped or paused the output. + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + + + + + + + Stops the output, pausing all musics/samples/streams. + + If successful, then is returned, else is returned. Use to get the error code. + + Use to resume the output and paused channels. + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + + + + + + + Sets the output master volume. + + The volume level... 0 (silent) to 1 (max). + If succesful, then is returned, else is returned. Use to get the error code. + + The actual volume level may not be exactly the same as requested, due to underlying precision differences. + can be used to confirm what the volume is. + This function affects the volume level of all applications using the same output device. + If you wish to only affect the level of your app's sounds, and/or the BASS_CONFIG_GVOL_MUSIC / BASS_CONFIG_GVOL_SAMPLE / BASS_CONFIG_GVOL_STREAM config options should be used instead. + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILThere is no volume control when using the "no sound" device. + BASS_ERROR_ILLPARAM is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Retrieves the current master volume level. + + If successful, the volume level is returned, else -1.0 is returned. Use to get the error code. + + The volume level... 0 (silent) to 1 (max) will be returned. + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILThere is no volume control when using the "no sound" device. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Sets the value of a config option. + + The option to set the value of... one of the following (). + The new option value (as an int). See the option's documentation for details on the possible values. + If successful, is returned, else is returned. Use to get the error code. + + Options: + + BASS_CONFIG_3DALGORITHMThe 3D algorithm for software mixed 3D channels. + newvalue (int): Use one of these algorithms + These algorithms only affect 3D channels that are being mixed in software. You can check if a channel is being software mixed with . + This config option allows you to use higher quality 3D processing on more powerful CPUs, and more efficient 3D processing on less powerful CPUs. Changing the algorithm only affects subsequently created or loaded samples, musics or streams, it does not affect those that already exist. + + BASS_CONFIG_BUFFERPlayback buffer length. + newvalue (int): The buffer length in milliseconds. The minimum length is 1ms above the update period (BASS_CONFIG_UPDATEPERIOD), the maximum is 5000 milliseconds. If the length specified is outside this range, it is automatically capped. + The default buffer length is 500 milliseconds. Increasing the length, decreases the chance of the sound possibly breaking-up on slower computers, but also increases the latency for DSP/FX. + Small buffer lengths are only required if the sound is going to be changing in real-time, for example, in a soft-synth. If you need to use a small buffer, then the minbuf member of BASS_INFO should be used to get the recommended minimum buffer length supported by the device and it's drivers. Even at this default length, it's still possible that the sound could break up on some systems, it's also possible that smaller buffers may be fine. So when using small buffers, you should have an option in your software for the user to finetune the length used, for optimal performance. + Using this config option only affects the HMUSIC/HSTREAM channels that you create afterwards, not the ones that have already been created. So you can have channels with differing buffer lengths by using this config option each time before creating them. + If automatic updating is disabled, make sure you call BASS_Update frequently enough to keep the buffers updated. + + BASS_CONFIG_DEV_BUFFERThe output device buffer length (Linux and Windows CE). + newvalue (int): The buffer length in milliseconds. + The device buffer is where the final mix of all playing channels is placed, ready for the device to play. Its length affects the latency of things like starting and stopping playback of a channel, so you will probably want to avoid setting it unnecessarily high, but setting it too short could result in breaks in the output. + When using a large device buffer, the attribute could be used to skip the channel buffering stage, to avoid further increasing latency for real-time generated sound and/or DSP/FX changes. + Changes to this config setting only affect subsequently initialized devices, not any that are already initialized. + This config option is only available on Linux and Windows CE. The device's buffer is determined automatically on other platforms. On Linux, the driver may choose to use a different buffer length if it decides that the specified length is too short or long. The buffer length actually being used can be obtained with , like this: latency + minbuf / 2. + + BASS_CONFIG_CURVE_VOLVolume translation curve. + newvalue (bool): Volume curve... = linear, = logarithmic. + DirectSound uses logarithmic volume and panning curves, which can be awkward to work with. + For example, with a logarithmic curve, the audible difference between 10000 and 9000, is not the same as between 9000 and 8000. + With a linear "curve" the audible difference is spread equally across the whole range of values, so in the previous example the audible difference between 10000 and 9000, and between 9000 and 8000 would be identical. + When using the linear curve, the volume range is from 0% (silent) to 100% (full). + When using the logarithmic curve, the volume range is from -100 dB (effectively silent) to 0 dB (full). For example, a volume level of 0.5 is 50% linear or -50 dB logarithmic. + The linear curve is used by default. + + BASS_CONFIG_CURVE_PANPanning translation curve. + newvalue (bool): Panning curve... = linear, = logarithmic. + The panning curve affects panning in exactly the same way as the volume curve (BASS_CONFIG_CURVE_VOL) affects the volume. + The linear curve is used by default. + + BASS_CONFIG_FLOATDSPPass 32-bit floating-point sample data to all DSP functions? + newvalue (bool): If , 32-bit floating-point sample data is passed to all callback functions. + Normally DSP functions receive sample data in whatever format the channel is using, ie. it can be 8, 16 or 32-bit. But using this config option, BASS will convert 8/16-bit sample data to 32-bit floating-point before passing it to DSP functions, and then convert it back after all the DSP functions are done. As well as simplifying the DSP code (no need for 8/16-bit processing), this also means that there is no degradation of quality as sample data passes through a chain of DSP. + This option also affects DX8 effects when using the "without FX flag" DX8 effect implementation. Note that floating-point FX processing requires DX9 or above. + + BASS_CONFIG_GVOL_MUSICGlobal music volume. + newvalue (int): MOD music global volume level... 0 (silent) - 10000 (full). + This config option allows you to have control over the volume levels of all the MOD musics, which is useful for setup options (eg. separate music and fx volume controls). + A channel's final volume = channel volume * global volume / max volume. So, for example, if a stream channel's volume is 0.5 and the global stream volume is 8000, then effectively the stream's volume level is 0.4 (0.5 * 8000 / 10000 = 0.4). + + BASS_CONFIG_GVOL_SAMPLEGlobal sample volume. + newvalue (int): Sample global volume level... 0 (silent) - 10000 (full). + This config option allows you to have control over the volume levels of all the samples, which is useful for setup options (eg. separate music and fx volume controls). + A channel's final volume = channel volume * global volume / max volume. So, for example, if a stream channel's volume is 0.5 and the global stream volume is 8000, then effectively the stream's volume level is 0.4 (0.5 * 8000 / 10000 = 0.4). + + BASS_CONFIG_GVOL_STREAMGlobal stream volume. + newvalue (int): Stream global volume level... 0 (silent) - 10000 (full). + This config option allows you to have control over the volume levels of all the streams, which is useful for setup options (eg. separate music and fx volume controls). + A channel's final volume = channel volume * global volume / max volume. So, for example, if a stream channel's volume is 0.5 and the global stream volume is 8000, then effectively the stream's volume level is 0.4 (0.5 * 8000 / 10000 = 0.4). + + BASS_CONFIG_MP3_CODECThe MP3 decoder to use. + newvalue (int): The MP3 decoder to use... 0 = BASS, 1 = Windows. + Most Windows users will have an MP3 codec installed - it comes preinstalled with modern Windows (ME/2K/XP), and can be installed on older Windows, eg. with Windows Media Player. By default, BASS will use it's own built-in MP3 decoder, as it provides better performance, but the Windows codec can be used instead. + When using the Windows codec, BASS still does the file processing, so all the usual features are still supported, including streaming, tag reading, pre-scanning, gapless playback, etc... + If the Windows codec option is chosen, but an MP3 codec is not installed, then MP3 files/streams will not be playable and the stream/sample creation functions will produce a BASS_ERROR_CODEC error. + + BASS_CONFIG_MUSIC_VIRTUALThe maximum number of virtual channels to use in the rendering of IT files. + newvalue (int): The number of virtual channels... 1 (min) - 512 (max). If the value specified is outside this range, it is automatically capped. + This setting only affects IT files, as the other MOD music formats do not have virtual channels. The default setting is 64. Changes only apply to subsequently loaded files, not any that are already loaded. + + BASS_CONFIG_NET_PLAYLISTProcess URLs in PLS and M3U playlists? + newvalue (int): When to process URLs in PLS and M3U playlists... 0 = never, 1 = in only, 2 = in and too. + + BASS_CONFIG_NET_BUFFERInternet download buffer length. + newvalue (int): The buffer length, in milliseconds. + Increasing the buffer length decreases the chance of the stream stalling, but also increases the time taken by to create the stream, as it has to pre-buffer more data (adjustable via the BASS_CONFIG_NET_PREBUF config option). Aside from the pre-buffering, this setting has no effect on streams without either the BASS_STREAM_BLOCK or BASS_STREAM_RESTRATE flags. + When streaming in blocks, this option determines the download buffer length. The effective buffer length can actually be a bit more than that specified, including data that's been read from the buffer by the decoder but not been used yet. + This config option also determines the buffering used by "buffered" user file streams created with . + The default buffer length is 5 seconds (5000 milliseconds). The net buffer length should be larger than the length of the playback buffer (BASS_CONFIG_BUFFER), otherwise the stream is likely to briefly stall soon after starting playback. + Using this config option only affects streams created afterwards, not any that have already been created. + + BASS_CONFIG_NET_PASSIVEUse passive mode in FTP connections? + passive (bool): If , passive mode is used, otherwise normal/active mode is used. + Changes take effect from the next internet stream creation call. By default, passive mode is disabled. + + BASS_CONFIG_NET_PREBUFAmount to pre-buffer when opening internet streams. + newvalue (int): Amount (percentage) to pre-buffer. + This setting determines what percentage of the buffer length (BASS_CONFIG_NET_BUFFER) should be filled by . The default is 75%. Setting this lower (eg. 0) is useful if you want to display a "buffering progress" (using ) when opening internet streams, but note that this setting is just a minimum - BASS will always pre-download a certain amount to verify the stream + As well as internet streams, this config setting also applies to "buffered" user file streams created with . + + BASS_CONFIG_NET_TIMEOUTTime to wait for a server to respond to a connection request. + newvalue (int): The time to wait, in milliseconds. + The default timeout is 5 seconds (5000 milliseconds). + + BASS_CONFIG_NET_READTIMEOUTThe time to wait for a server to deliver more data for an internet stream. + newvalue (int): The time to wait, in milliseconds... 0 = no timeout. + When the timeout is hit, the connection with the server will be closed. The default setting is 0, no timeout. + + BASS_CONFIG_PAUSE_NOPLAYPrevent channels being played when the output is paused? + newvalue (bool): If , channels can't be played while the output is paused. + When the output is paused using , and this config option is enabled, channels can't be played until the output is resumed using . Attempts to play a channel will give a BASS_ERROR_START error. + + BASS_CONFIG_REC_BUFFERThe buffer length for recording channels. + newvalue (int): The buffer length in milliseconds... 1000 (min) - 5000 (max). If the length specified is outside this range, it is automatically capped. + Unlike a playback buffer, where the aim is to keep the buffer full, a recording buffer is kept as empty as possible and so this setting has no effect on latency. The default recording buffer length is 2000 milliseconds. Unless processing of the recorded data could cause significant delays, or you want to use a large recording period with , there should be no need to increase this. + Using this config option only affects the recording channels that are created afterwards, not any that have already been created. So it is possible to have channels with differing buffer lengths by using this config option each time before creating them. + + BASS_CONFIG_SRCThe default sample rate conversion quality. + quality (int): The sample rate conversion quality... 0 = linear interpolation, 1 = 8 point sinc interpolation, 2 = 16 point sinc interpolation, 3 = 32 point sinc interpolation. Other values are also accepted. + This config option determines what sample rate conversion quality new channels will initially have, except for sample channels (HCHANNEL), which use the setting. + A channel's sample rate conversion quality can subsequently be changed via the attribute. + The default setting is 1 (8 point sinc interpolation). + + BASS_CONFIG_SRC_SAMPLEThe default sample rate conversion quality for samples. + quality (int): The sample rate conversion quality... 0 = linear interpolation, 1 = 8 point sinc interpolation, 2 = 16 point sinc interpolation, 3 = 32 point sinc interpolation. Other values are also accepted. + This config option determines what sample rate conversion quality a new sample channel will initially have, following a call. + The channel's sample rate conversion quality can subsequently be changed via the attribute. + The default setting is 0 (linear interpolation). + + BASS_CONFIG_UPDATEPERIODUpdate period of playback buffers. + newvalue (int): The update period in milliseconds... 0 = disable automatic updating. The minimum period is 5ms, the maximum is 100ms. If the period specified is outside this range, it is automatically capped. + The update period is the amount of time between updates of the playback buffers of HSTREAM/HMUSIC channels. Shorter update periods allow smaller buffers to be set with the BASS_CONFIG_BUFFER config option, but as the rate of updates increases, so the overhead of setting up the updates becomes a greater part of the CPU usage. The update period only affects HSTREAM and HMUSIC channels, it does not affect samples. Nor does it have any effect on decoding channels, as they are not played. + BASS creates a thread specifically to perform the updating, except when automatic updating is disabled (period=0) - then you must regularly call instead. This allows you to synchronize BASS's CPU usage with your program's. For example, in a game loop you could call once per frame, which keeps all the processing in sync so that the frame rate is as smooth as possible. should be called at least around 8 times per second, even more often if the BASS_CONFIG_BUFFER config option is used to set smaller buffers. + The update period can be altered at any time, including during playback. The default period is 100ms. + + BASS_CONFIG_UPDATETHREADSNumber of update threads. + newvalue (int): The number of threads to use... 0 = disable automatic updating. + The number of update threads determines how many HSTREAM/HMUSIC channel playback buffers can be updated in parallel; each thread can process one channel at a time. The default is to use a single thread, but additional threads can be used to take advantage of multiple CPU cores. There is generally nothing much to be gained by creating more threads than there are CPU cores, but one benefit of using multiple threads even with a single CPU core is that a slow updating channel need not delay the updating of other channels. + When automatic updating is disabled (threads = 0), or should be used instead. + The number of update threads can be changed at any time, including during playback. + + BASS_CONFIG_VERIFYThe amount of data to check in order to verify/detect the file format. + length (int): The amount of data to check, in bytes... 1000 (min) to 100000 (max). If the value specified is outside this range, it is automatically capped. + Of the file formats supported as standard, this setting only affects the detection of MP3/MP2/MP1 formats, + but it may also be used by add-ons (see the documentation). For internet (and "buffered" user file) streams, a quarter of the length is used, up to a minimum of 1000 bytes. + The verification length excludes any tags that may be at the start of the file. The default length is 16000 bytes. + + + Other config options may be supported by Add-Ons, see the documentation. + + + + ERROR CODEDescription + BASS_ERROR_ILLPARAM is invalid. + + + + Setting the playback buffer to 100ms and the update period to 20ms: + + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_BUFFER, 100); + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 20); + + + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_BUFFER, 100) + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 20) + + + + + + Sets the value of a config option. + + The option to set the value of... one of the following (). + The new option value (as a bool). See the option's documentation for details on the possible values. + If successful, is returned, else is returned. Use to get the error code. + + Options: + + BASS_CONFIG_CURVE_VOLVolume translation curve. + newvalue (bool): Volume curve... = linear, = logarithmic. + DirectSound uses logarithmic volume and panning curves, which can be awkward to work with. + For example, with a logarithmic curve, the audible difference between 10000 and 9000, is not the same as between 9000 and 8000. + With a linear "curve" the audible difference is spread equally across the whole range of values, so in the previous example the audible difference between 10000 and 9000, and between 9000 and 8000 would be identical. + When using the linear curve, the volume range is from 0% (silent) to 100% (full). + When using the logarithmic curve, the volume range is from -100 dB (effectively silent) to 0 dB (full). For example, a volume level of 0.5 is 50% linear or -50 dB logarithmic. + The linear curve is used by default. + + BASS_CONFIG_CURVE_PANPanning translation curve. + newvalue (bool): Panning curve... = linear, = logarithmic. + The panning curve affects panning in exactly the same way as the volume curve (BASS_CONFIG_CURVE_VOL) affects the volume. + The linear curve is used by default. + + BASS_CONFIG_FLOATDSPPass 32-bit floating-point sample data to all DSP functions? + newvalue (bool): If , 32-bit floating-point sample data is passed to all callback functions. + Normally DSP functions receive sample data in whatever format the channel is using, ie. it can be 8, 16 or 32-bit. But using this config option, BASS will convert 8/16-bit sample data to 32-bit floating-point before passing it to DSP functions, and then convert it back after all the DSP functions are done. As well as simplifying the DSP code (no need for 8/16-bit processing), this also means that there is no degradation of quality as sample data passes through a chain of DSP. + This option also affects DX8 effects when using the "without FX flag" DX8 effect implementation. Note that floating-point FX processing requires DX9 or above. + + BASS_CONFIG_MP3_CODECThe MP3 decoder to use. + newvalue (bool): The MP3 decoder to use... = BASS, = Windows. + Most Windows users will have an MP3 codec installed - it comes preinstalled with modern Windows (ME/2K/XP), and can be installed on older Windows, eg. with Windows Media Player. By default, BASS will use it's own built-in MP3 decoder, as it provides better performance, but the Windows codec can be used instead. + When using the Windows codec, BASS still does the file processing, so all the usual features are still supported, including streaming, tag reading, pre-scanning, gapless playback, etc... + If the Windows codec option is chosen, but an MP3 codec is not installed, then MP3 files/streams will not be playable and the stream/sample creation functions will produce a BASS_ERROR_CODEC error. + + BASS_CONFIG_NET_PASSIVEUse passive mode in FTP connections? + passive (bool): If , passive mode is used, otherwise normal/active mode is used. + Changes take effect from the next internet stream creation call. By default, passive mode is disabled. + + BASS_CONFIG_PAUSE_NOPLAYPrevent channels being played when the output is paused? + newvalue (bool): If , channels can't be played while the output is paused. + When the output is paused using , and this config option is enabled, channels can't be played until the output is resumed using . Attempts to play a channel will give a BASS_ERROR_START error. + + BASS_CONFIG_DEV_DEFAULTInclude a 'Default' entry in the output device list? + default (bool): If , a 'Default' device will be included in the device list. + BASS does not usually include a 'Default' entry in its device list, as that would ultimately map to one of the other devices and be a duplicate entry. When the default device is requested in a call (with device = -1), BASS will check the default device at that time, and initialize it. But Windows 7 has the ability to automatically switch the default output to the new default device whenever it changes, and in order for that to happen, the default device (rather than a specific device) needs to be used. That is where this option comes in. + When enabled, the 'Default' device will also become the default device to (with device = -1). When the "Default" device is used, the and functions work a bit differently to usual; they deal with the "session" volume, which only affects the current process's output on the device, rather than the device's volume. + This option can only be set before or has been called. + This config option is only available on Windows. It is available on all Windows versions (not including CE), but only Windows 7 has the default output switching feature. + + BASS_CONFIG_VISTA_SPEAKERSEnable speaker assignment with panning/balance control on Windows Vista and newer? + enable (bool): If , speaker assignment with panning/balance control is enabled on Windows Vista and newer. + Panning/balance control via the attribute is not available when speaker assignment is used on Windows due to the way that the speaker assignment needs to be implemented there. The situation is improved with Windows Vista, and speaker assignment can generally be done in a way that does permit panning/balance control to be used at the same time, but there may still be some drivers that it does not work properly with, so it is disabled by default and can be enabled via this config option. Changes only affect channels that are created afterwards, not any that already exist. + Platform-specific: This config option is only available on Windows. It is available on all Windows versions (not including CE), but only has effect on Windows Vista and newer. Speaker assignment with panning/balance control is always possible on other platforms, where BASS generates the final mix. + + + Other config options may be supported by Add-Ons, see the documentation. + + + + ERROR CODEDescription + BASS_ERROR_ILLPARAM is invalid. + + + + Setting the DSP processing to 32-bit float: + + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_FLOATDSP, true); + + + Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_FLOATDSP, True) + + + + + + Sets the value of a pointer config option. + + The option to set the value of... one of the following (). + The new option value (as an IntPtr). See the option's documentation for details on the possible values. + If successful, is returned, else is returned. Use to get the error code. + + Options: + + BASS_CONFIG_NET_AGENT"User-Agent" header. + newvalue (IntPtr): The "User-Agent" header. + BASS does not make a copy of the header string, so it must reside in the heap (not the stack), eg. a global variable - see example below! + This also means that the agent setting can subsequently be changed at that location without having to call this function again. + Changes take effect from the next internet stream creation call. + + BASS_CONFIG_NET_PROXYProxy server settings. + newvalue (IntPtr): The "User-Agent" header. + The proxy server settings, in the form of "user:pass@server:port"... = don't use a proxy. "" (empty string) = use the default proxy settings. + If only the "user:pass@" part is specified, then those authorization credentials are used with the default proxy server. + If only the "server:port" part is specified, then that proxy server is used without any authorization credentials. + BASS does not make a copy of the proxy string, so it must reside in the heap (not the stack), eg. a global variable - see example below! + This also means that the proxy setting can subsequently be changed at that location without having to call this function again. + Changes take effect from the next internet stream creation call. By default, BASS will use the Windows proxy settings, as set in the Internet Properties control panel. + + + Other config options may be supported by Add-Ons, see the documentation. + + + + ERROR CODEDescription + BASS_ERROR_ILLPARAM is invalid. + + + + + As the BASS_CONFIG_NET_PROXY and BASS_CONFIG_NET_AGENT options take a pointer to an ANSI string + as an argument you must first marshal a string to a heap pointer and pin it, so that the garbage collector can not re-locate it. + The following example copies the contents of a managed String into unmanaged memory: + + public IntPtr _myUserAgentPtr; + ... + // create an unmanaged pointer containing a copy of the string + _myUserAgentPtr = Marshal.StringToHGlobalAnsi("radio42"); + Bass.BASS_SetConfigPtr(BASSConfig.BASS_CONFIG_NET_AGENT, _myUserAgentPtr); + ... + // make sure to free the myUserAgentPtr!!! + // e.g. when you dispose your class or application + Marshal.FreeHGlobal(_myUserAgentPtr); + + + Public _myUserAgentPtr As IntPtr + ... + ' create an unmanaged pointer containing a copy of the string + _myUserAgentPtr = Marshal.StringToHGlobalAnsi("radio42") + Bass.BASS_SetConfigPtr(BASSConfig.BASS_CONFIG_NET_AGENT, _myUserAgentPtr) + ... + ' make sure to free the myUserAgentPtr!!! + ' e.g. when you dispose your class or application + Marshal.FreeHGlobal(_myUserAgentPtr) + + If you need to dynamically change the BASS_CONFIG_NET_PROXY or BASS_CONFIG_NET_AGENT option, + you will need to call each time again! + + public static string _myUserAgent = "radio42"; + public IntPtr _myUserAgentPtr; + ... + // create an unmanaged pointer containing a copy of the string + _myUserAgentPtr = Marshal.StringToHGlobalAnsi(_myUserAgent); + Bass.BASS_SetConfigPtr(BASSConfig.BASS_CONFIG_NET_AGENT, _myUserAgentPtr); + ... + // change it to a new value, + // but first free the previous one + Marshal.FreeHGlobal(_myUserAgentPtr); + // then assign the new value + _myUserAgent = "new value"; + _myUserAgentPtr = Marshal.StringToHGlobalAnsi(_myUserAgent); + Bass.BASS_SetConfigPtr(BASSConfig.BASS_CONFIG_NET_AGENT, _myUserAgentPtr); + ... + // make sure to free the myUserAgentPtr!!! + // e.g. when you dispose your class or application + Marshal.FreeHGlobal(_myUserAgentPtr); + + + Public Shared _myUserAgent As String = "radio42" + Public _myUserAgentPtr As IntPtr + ... + ' create an unmanaged pointer containing a copy of the string + _myUserAgentPtr = Marshal.StringToHGlobalAnsi(_myUserAgent) + Bass.BASS_SetConfigPtr(BASSConfig.BASS_CONFIG_NET_AGENT, _myUserAgentPtr) + ... + ' change it to a new value, + ' but first free the previous one + Marshal.FreeHGlobal(_myUserAgentPtr) + ' then assign the new value + _myUserAgent = "new value" + _myUserAgentPtr = Marshal.StringToHGlobalAnsi(_myUserAgent) + Bass.BASS_SetConfigPtr(BASSConfig.BASS_CONFIG_NET_AGENT, _myUserAgentPtr) + ... + ' make sure to free the myUserAgentPtr!!! + ' e.g. when you dispose your class or application + Marshal.FreeHGlobal(_myUserAgentPtr) + + An alternative way of creating a pointer to a managed object and pinning it + is the use of GCHandle: + + private GCHandle _userAgentGCH; + ... + string userAgent = "BASS.NET"; + byte[] userAgentBytes = Encoding.Default.GetBytes(userAgent); + // create a pinned handle to our managed object + _userAgentGCH = GCHandle.Alloc(userAgentBytes, GCHandleType.Pinned); + // use the pointer to the string + Bass.BASS_SetConfigPtr(BASSConfig.BASS_CONFIG_NET_AGENT, _userAgentGCH.AddrOfPinnedObject()); + ... + // make sure to free the handle when you don't need it anymore! + // e.g. when you dispose your class or application + _userAgentGCH.Free(); + + + Private _userAgentGCH As GCHandle + ... + Dim userAgent As String = "BASS.NET" + Dim userAgentBytes As Byte() = Encoding.Default.GetBytes(userAgent) + ' create a pinned handle to our managed object + _userAgentGCH = GCHandle.Alloc(userAgentBytes, GCHandleType.Pinned) + ' use the pointer to the string + Bass.BASS_SetConfigPtr(BASSConfig.BASS_CONFIG_NET_AGENT, _userAgentGCH.AddrOfPinnedObject()) + ... + ' make sure to free the handle when you don't need it anymore! + ' e.g. when you dispose your class or application + _userAgentGCH.Free() + + + + + + Retrieves the value of a config option. + + The option to get the value of... one of the following (). + If successful, the value of the requested config option is returned (as an int), else -1 is returned. Use to get the error code. + + Options: + + BASS_CONFIG_3DALGORITHMThe 3D algorithm for software mixed 3D channels. + BASS_CONFIG_BUFFERPlayback buffer length. + BASS_CONFIG_CURVE_VOLVolume translation curve. + BASS_CONFIG_CURVE_PANPanning translation curve. + BASS_CONFIG_DEV_BUFFEROutput device buffer length (Linux and Windows CE only). + BASS_CONFIG_DEV_DEFAULTInclude a "Default" entry in the output device list? + BASS_CONFIG_FLOATDSPPass 32-bit floating-point sample data to all DSP functions? + BASS_CONFIG_GVOL_MUSICGlobal music volume. + BASS_CONFIG_GVOL_SAMPLEGlobal sample volume. + BASS_CONFIG_GVOL_STREAMGlobal stream volume. + BASS_CONFIG_MP3_CODECThe MP3 decoder to use... 0 = BASS, 1 = Windows. + BASS_CONFIG_MUSIC_VIRTUALThe maximum number of virtual channels to use in the rendering of IT files. + BASS_CONFIG_NET_PLAYLISTProcess URLs in PLS and M3U playlists? + BASS_CONFIG_NET_BUFFERInternet download buffer length. + BASS_CONFIG_NET_PROXYProxy server settings. + BASS_CONFIG_NET_PASSIVEUse passive mode in FTP connections? + BASS_CONFIG_NET_PREBUFAmount to pre-buffer when opening internet streams. + BASS_CONFIG_NET_TIMEOUTTime to wait for a server to respond to a connection request. + BASS_CONFIG_NET_READTIMEOUTTime to wait for a server to deliver more data. + BASS_CONFIG_PAUSE_NOPLAYPrevent channels being played when the output is paused? + BASS_CONFIG_REC_BUFFERRecording buffer length. + BASS_CONFIG_SRCDefault sample rate conversion quality. + BASS_CONFIG_SRC_SAMPLEDefault sample rate conversion quality for samples. + BASS_CONFIG_UPDATEPERIODUpdate period of playback buffers. + BASS_CONFIG_UPDATETHREADSNumber of update threads. + BASS_CONFIG_VERIFYFile format verification length. + + Other config options may be supported by Add-Ons, see the documentation. + + + + ERROR CODEDescription + BASS_ERROR_ILLPARAM is invalid. + + + + Getting the current playback buffer length: + + int bufLen = Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_BUFFER); + + + Dim bufLen As Integer = Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_BUFFER) + + + + + + Retrieves the value of a config option as a bool. + + The option to get the value of... one of the following (). + If successful, the value of the requested config option is returned (as a bool). Use to get the error code. + + Options: + + BASS_CONFIG_CURVE_VOLVolume translation curve. + BASS_CONFIG_CURVE_PANPanning translation curve. + BASS_CONFIG_FLOATDSPPass 32-bit floating-point sample data to all DSP functions? + BASS_CONFIG_MP3_CODECThe MP3 decoder to use... = BASS, = Windows. + BASS_CONFIG_NET_PASSIVEUse passive mode in FTP connections? + BASS_CONFIG_PAUSE_NOPLAYPrevent channels being played when the output is paused? + BASS_CONFIG_VISTA_SPEAKERSEnable speaker assignment with panning/balance control on Windows Vista and newer? + + Other config options may be supported by Add-Ons, see the documentation. + + + + ERROR CODEDescription + BASS_ERROR_ILLPARAM is invalid. + + + + Getting the DSP processing option: + + bool floatDSP = Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_FLOATDSP); + + + Dim floatDSP As Boolean = Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_FLOATDSP) + + + + + + Retrieves the value of a pointer config option. + + The option to get the value of...(see ). + If successful, the value of the requested config option is returned (as an IntPtr). Use to get the error code. + + Options: + + BASS_CONFIG_NET_AGENT"User-Agent" header. + BASS_CONFIG_NET_PROXYProxy server settings. + + Other config options may be supported by Add-Ons, see the documentation. + + + + ERROR CODEDescription + BASS_ERROR_ILLPARAM is invalid. + + + + Getting the current user agent header: + + string userAgent = String.Empty; + IntPtr p = Bass.BASS_GetConfigPtr(BASSConfig.BASS_CONFIG_NET_AGENT); + if (p != IntPtr.Zero) + { + userAgent = Marshal.PtrToStringAnsi(p); + } + + + Dim userAgent As String = [String].Empty + Dim p As IntPtr = Bass.BASS_GetConfigPtr(BASSConfig.BASS_CONFIG_NET_AGENT) + If p <> IntPtr.Zero Then + userAgent = Marshal.PtrToStringAnsi(p) + End If + + + + + + Retrieves the value of a pointer config option as an Ansi string. + + The option to get the value of... one of the following (). + If successful, the value of the requested config option is returned (as an Ansi String). Use to get the error code. + + Options: + + BASS_CONFIG_NET_AGENT"User-Agent" header. + BASS_CONFIG_NET_PROXYProxy server settings. + + Other config options may be supported by Add-Ons, see the documentation. + + + + ERROR CODEDescription + BASS_ERROR_ILLPARAM is invalid. + + + + Getting the current user agent header: + + string userAgent = Bass.BASS_GetConfigString(BASSConfig.BASS_CONFIG_NET_AGENT); + if (userAgent != null) + { + ... + } + + + Dim userAgent As String = Bass.BASS_GetConfigString(BASSConfig.BASS_CONFIG_NET_AGENT) + If Not (userAgent Is Nothing) Then + ... + End If + + + + + + + + + + + + + + Plugs on "add-on" into the standard stream and sample creation functions. + This overload implements the Unicode version for the file name. + + Filename of the add-on/plugin. + If successful, the loaded plugin's handle is returned, else 0 is returned. Use to get the error code. + + Support for additional file formats is available via add-ons, which can be downloaded from the BASS website: www.un4seen.com. + There are 2 ways in which add-ons can provide support for additional formats. They can provide dedicated functions to create streams of the specific format(s) they support and/or they can plug into the standard stream creation functions - , and . + This function enables the latter method. Both methods can be used side by side. The obvious advantage of the plugin system is convenience, while the dedicated functions can provide extra options that are not possible via the shared function interfaces. See an add-on's documentation for more specific details on it. + As well as the stream creation functions, plugins also add their additional format support to . + When using multiple plugins, the stream/sample creation functions will try each of them in the order that they were loaded via this function, until one that accepts the file is found. + When an add-on is already loaded (eg. if you're using functions from it), the plugin system will use the same instance (the reference count will just be incremented), ie. there won't be 2 copies of the add-on in memory. + Note: Only stream/music add-ons are loaded (e.g. bass_fx.dll or bassmix.dll are NOT loaded). + + + ERROR CODEDescription + BASS_ERROR_FILEOPENThe could not be opened. + BASS_ERROR_FILEFORMThe is not a plugin. + BASS_ERROR_ALREADYThe is already plugged in. + + + + + Add-On residing in same directory: + + // load the FLAC add-on + int pluginFlac = Bass.BASS_PluginLoad("bassflac.dll"); + ... + // use the add-on + int stream = Bass.BASS_StreamCreateFile("file.flac", 0, 0, BASSFlag.BASS_DEFAULT); + ... + // un-load the FLAC add-on + Bass.BASS_PluginFree(pluginFlac); + + + ' load the FLAC add-on + Dim pluginFlac As Integer = Bass.BASS_PluginLoad("bassflac.dll") + ... + ' use the add-on + Dim stream As Integer = Bass.BASS_StreamCreateFile("file.flac", 0, 0, BASSFlag.BASS_DEFAULT) + ... + ' un-load the FLAC add-on + Bass.BASS_PluginFree(pluginFlac) + + + + + + Unplugs an add-on. + + The plugin handle... 0 = all plugins. + If successful, is returned, else is returned. Use to get the error code. + If there are streams created by a plugin in existence when it is being freed, the streams will automatically be freed too. Samples loaded by the plugin are unaffected as the plugin has nothing to do with them once they are loaded (the sample data is already fully decoded). + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + Add-On residing in same directory: + + // load the FLAC add-on + int pluginFlac = Bass.BASS_PluginLoad("bassflac.dll"); + ... + // use the add-on + int stream = Bass.BASS_StreamCreateFile("file.flac", 0, 0, BASSFlag.BASS_DEFAULT); + ... + // un-load the FLAC add-on + Bass.BASS_PluginFree(pluginFlac); + + + ' load the FLAC add-on + Dim pluginFlac As Integer = Bass.BASS_PluginLoad("bassflac.dll") + ... + ' use the add-on + Dim stream As Integer = Bass.BASS_StreamCreateFile("file.flac", 0, 0, BASSFlag.BASS_DEFAULT) + ... + ' un-load the FLAC add-on + Bass.BASS_PluginFree(pluginFlac) + + + + + + Tries to loads all BASS add-ons (bass*.dll) contained in the specified directory. + + The directory in which to search for BASS add-ons (bass*.dll). + A hash table containing all successfully loaded BASS add-ons. + The hash table will be constructed as: Key=pluginHandle and Value=filename. + Note: Only stream/music add-ons are loaded (e.g. bass_fx.dll or bassenc.dll are NOT loaded). + + Internally the method will be used to load all add-ons contained in the specified directory folder (sub-folders are not scanned as well). + + + Dictionary<int, string> loadedPlugIns = Bass.BASS_PluginLoadDirectory("C:\\BASS"); + if (loadedPlugIns != null) + { + foreach (string file in loadedPlugIns.Values) + Console.Writeln( file ); + } + + + Dim loadedPlugIns As Dictionary(Of Integer, String) = Bass.BASS_PluginLoadDirectory("C:\BASS") + If Not (loadedPlugIns Is Nothing) Then + Dim file As String + For Each file In loadedPlugIns.Values + Console.Writeln(file) + Next file + End If + + + + + + + + + + + + + Retrieves information on a plugin. + + The plugin handle - or 0 to retrieve native BASS information. + If successful, an instance of is returned, else is returned. Use to get the error code. + The plugin information does not change, so the returned info remains valid for as long as the plugin is loaded. + Note: There is no guarantee that the check is complete or might contain formats not being supported on your particular OS/machine (due to additional or missing audio codecs). + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + List the formats supported by a plugin: + + int pluginFlac = Bass.BASS_PluginLoad("bassflac.dll"); + BASS_PLUGININFO info = Bass.BASS_PluginGetInfo(pluginFlac); + foreach (BASS_PLUGINFORM f in info.formats) + Console.WriteLine("Type={0}, Name={1}, Exts={2}", f.ctype, f.name, f.exts); + + + Dim pluginFlac As Integer = Bass.BASS_PluginLoad("bassflac.dll") + Dim info As BASS_PLUGININFO = Bass.BASS_PluginGetInfo(pluginFlac) + Dim f As BASS_PLUGINFORM + For Each f In info.formats + Console.WriteLine("Type={0}, Name={1}, Exts={2}", f.ctype, f.name, f.exts) + Next f + + + + + + Retrieves the current type of EAX environment and it's parameters. + + The EAX environment to get (one of the values). + The volume of the reverb. + The decay duration. + The damping. + If succesful, then is returned, else is returned. Use to get the error code. + + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOEAXThe current device does not support EAX. + + + Platform-specific + EAX and this function are only available on Windows + + + Get the current EAX environment and all it's settings: + + EAXEnvironment env = EAXEnvironment.EAX_ENVIRONMENT_LEAVECURRENT; + float vol = 0f; + float decay = 0f; + float damp = 0f; + if (Bass.BASS_GetEAXParameters(ref env, ref vol, ref decay, ref damp)) + Console.WriteLine("Env={0}, Vol={1}, Decay={2}, Damp={3}", env, vol, decay, damp); + + + Dim env As EAXEnvironment = EAXEnvironment.EAX_ENVIRONMENT_LEAVECURRENT + Dim vol As Single = 0F + Dim decay As Single = 0F + Dim damp As Single = 0F + If Bass.BASS_GetEAXParameters(env, vol, decay, damp) Then + Console.WriteLine("Env={0}, Vol={1}, Decay={2}, Damp={3}", env, vol, decay, damp) + End If + + + + + + Retrieves the current type of EAX environment and it's parameters. + Note: This is a generic overload using object references, so that you can pass values as in the C++ interface. + So make sure to pass object references of the currect type into this method and cast the return value back to the correct data types! + + The EAX environment (int)... = don't retrieve it. See for a list of the possible environments (or use one of these values, which need to be casted into an (object) here). + The volume of the reverb (float)... = don't retrieve it. + The decay duration (float)... = don't retrieve it. + The damping (float)... = don't retrieve it. + If succesful, then is returned, else is returned. Use to get the error code. + + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOEAXThe current device does not support EAX. + + + + + Get the current environment setting and volume: + + object env = EAXEnvironment.EAX_ENVIRONMENT_LEAVECURRENT; + object vol = 0f; + if ( Bass.BASS_GetEAXParameters( env, vol, null, null ) ) + { + // env needs to be casted back to an EAXEnvironment + // vol needs to be casted back to float + Console.WriteLine( "Env={0}, Vol={1}", (EAXEnvironment)env, (float)vol ); + } + else + Console.WriteLine( "Bass_Init error OR Device does not support EAX!" ); + + + Dim env As Object = EAXEnvironment.EAX_ENVIRONMENT_LEAVECURRENT + Dim vol As Object = 0F + If Bass.BASS_GetEAXParameters(env, vol, Nothing, Nothing) Then + ' env needs to be casted back to an EAXEnvironment + ' vol needs to be casted back to float + Console.WriteLine("Env={0}, Vol={1}", CType(env, EAXEnvironment), CSng(vol)) + Else + Console.WriteLine("Bass_Init error OR Device does not support EAX!") + End If + + + + + + Sets the type of EAX environment and it's parameters. + + The EAX environment... -1 = leave current, or one of the these . + The volume of the reverb... 0.0 (off) - 1.0 (max), less than 0.0 = leave current. + The time in seconds it takes the reverb to diminish by 60dB... 0.1 (min) - 20.0 (max), less than 0.0 = leave current. + The damping, high or low frequencies decay faster... 0.0 = high decays quickest, 1.0 = low/high decay equally, 2.0 = low decays quickest, less than 0.0 = leave current. + If succesful, then is returned, else is returned. Use to get the error code. + + Obviously, EAX functions have no effect if no EAX supporting device is used. You can use to check if the current device suports EAX. EAX only affects 3D channels, but EAX functions do NOT require to apply the changes. + Presets are provided for all the EAX environments. To use a preset, simply call , with the 'preset' overload set to one of these values. + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOEAXThe current device does not support EAX. + + + Platform-specific + This function is only available on Windows. + + + Leave the currect environment and damping, but set the volume and decay duration: + + Bass.BASS_SetEAXParameters( EAXEnvironment.EAX_ENVIRONMENT_LEAVECURRENT, 0.3f, 1f, -1f ); + + + Bass.BASS_SetEAXParameters( EAXEnvironment.EAX_ENVIRONMENT_LEAVECURRENT, 0.3F, 1F, -1F ) + + + + + + Overload implementing the use of . + A preset already sets prediefined values for "vol", "decay" and "damp". + + The to use and set. + If succesful, then is returned, else is returned. Use to get the error code. + + Obviously, EAX functions have no effect if no EAX supporting device is used. You can use to check if the current device suports EAX. EAX only affects 3D channels, but EAX functions do NOT require to apply the changes. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOEAXThe current device does not support EAX. + + + + Use the EAX_PRESET_ARENA preset: + + Bass.BASS_SetEAXParameters(EAXPreset.EAX_PRESET_ARENA); + + + Bass.BASS_SetEAXParameters(EAXPreset.EAX_PRESET_ARENA) + + + + + + Applies changes made to the 3D system. + + + This must be called to apply any changes made with , , or . + It improves performance to have DirectSound do all the required recalculating at the same time like this, rather than recalculating after every little change is made. + This function applies 3D changes on all the initialized devices - there's no need to re-call it for each individual device when using multiple devices. + + + + + Sets the factors that affect the calculations of 3D sound. + + The distance factor... less than 0.0 = leave current... examples: 1.0 = use meters, 0.9144 = use yards, 0.3048 = use feet. By default BASS measures distances in meters, you can change this setting if you are using a different unit of measurement. + The rolloff factor, how fast the sound quietens with distance... 0.0 (min) - 10.0 (max), less than 0.0 = leave current... examples: 0.0 = no rolloff, 1.0 = real world, 2.0 = 2x real. + The doppler factor... 0.0 (min) - 10.0 (max), less than 0.0 = leave current... examples: 0.0 = no doppler, 1.0 = real world, 2.0 = 2x real. The doppler effect is the way a sound appears to change pitch when it is moving towards or away from you (say hello to Einstein!). The listener and sound velocity settings are used to calculate this effect, this doppf value can be used to lessen or exaggerate the effect. + If succesful, then is returned, else is returned. Use to get the error code. + + As with all 3D functions, use to apply the changes. + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NO3DThe device was not initialized with 3D support. + + + + + To use yards as the distance measurement unit, while leaving the current rolloff and doppler factors untouched: + + Bass.BASS_Set3DFactors(0.9144f, -1f, -1f); + Bass.BASS_Apply3D(); // apply the change + + + Bass.BASS_Set3DFactors(0.9144F, -1F, -1F) + Bass.BASS_Apply3D() ' apply the change + + + + + + Retrieves the factors that affect the calculations of 3D sound. + This overload allows you to only get all three values at a time. + + The distance factor. + The rolloff factor. + The doppler factor. + If succesful, then is returned, else is returned. Use to get the error code. + + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NO3DThe device was not initialized with 3D support. + + + + + + float distf = 0f; + float rollf = 0f; + float doppf = 0f; + Bass.BASS_Get3DFactors(ref distf, ref rollf, ref doppf); + + + Dim distf As Single = 0F + Dim rollf As Single = 0F + Dim doppf As Single = 0F + Bass.BASS_Get3DFactors(distf, rollf, doppf) + + + + + + Retrieves the factors that affect the calculations of 3D sound. + This overload uses objects (so you can pass in order to NOT retrieve a value). However a requested return value needs to be casted back into a float after getting it. + + The distance factor... = don't retrieve it. + The rolloff factor... = don't retrieve it. + The doppler factor... = don't retrieve it. + If succesful, then is returned, else is returned. Use to get the error code. + + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NO3DThe device was not initialized with 3D support. + + + + + Only get the distance factor: + + object distf = 0f; + Bass.BASS_Get3DFactors(distf, null, null); + float distanceFactor = (float)distf; + + + Dim distf As Object = 0F + Bass.BASS_Get3DFactors(distf, Nothing, Nothing) + Dim distanceFactor As Single = CSng(distf) + + + + + + Retrieves the position, velocity, and orientation of the listener. + + The position of the listener... = don't retrieve it. + The listener's velocity... = don't retrieve it. + The direction that the listener's front is pointing... =don't retrieve it. + The direction that the listener's top is pointing... = don't retrieve it. + If succesful, then is returned, else is returned. Use to get the error code. + + The and parameters must both be retrieved in a single call, they can not be retrieved individually. + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NO3DThe device was not initialized with 3D support. + + + + + Set the current listener position only: + + BASS_3DVECTOR pos = new BASS_3DVECTOR(); + Bass.BASS_Set3DPosition(pos, null, null, null); + + + Dim pos As New BASS_3DVECTOR() + Bass.BASS_Set3DPosition(pos, Nothing, Nothing, Nothing) + + Updates the position, velocity and top of the listener: + + BASS_3DVECTOR position = new BASS_3DVECTOR(camera.RealPosition.x, camera.RealPosition.y, camera.RealPosition.z); + BASS_3DVECTOR direction = new BASS_3DVECTOR(camera.RealDirection.x, camera.RealDirection.y, camera.RealDirection.z); + BASS_3DVECTOR up = new BASS_3DVECTOR(-camera.RealUp.x, -camera.RealUp.y, -camera.RealUp.z); + + if (!Bass.BASS_Set3DPosition(position, velocity, direction, up)) + throw new AudioException("Could not set the 3d position of the listener", "listener", Bass.BASS_ErrorGetCode()); + + Bass.BASS_Apply3D(); + + + Dim position As New BASS_3DVECTOR(camera.RealPosition.x, camera.RealPosition.y, camera.RealPosition.z) + Dim direction As New BASS_3DVECTOR(camera.RealDirection.x, camera.RealDirection.y, camera.RealDirection.z) + Dim up As New BASS_3DVECTOR(-camera.RealUp.x, -camera.RealUp.y, -camera.RealUp.z) + + If Not Bass.BASS_Set3DPosition(position, velocity, direction, up) Then + Throw New AudioException("Could not set the 3d position of the listener", "listener", Bass.BASS_ErrorGetCode()) + End If + + Bass.BASS_Apply3D() + + + + + + Retrieves the position, velocity, and orientation of the listener. + + The position of the listener... = don't retrieve it. + The listener's velocity... = don't retrieve it. + The direction that the listener's front is pointing... =don't retrieve it. + The direction that the listener's top is pointing... = don't retrieve it. + If succesful, then is returned, else is returned. Use to get the error code. + + The and parameters must both be retrieved in a single call, they can not be retrieved individually. + When using multiple devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NO3DThe device was not initialized with 3D support. + + + + + Get the current listener position only: + + BASS_3DVECTOR pos = new BASS_3DVECTOR(); + Bass.BASS_Get3DPosition(pos, null, null, null); + + + Dim pos As New BASS_3DVECTOR() + Bass.BASS_Get3DPosition(pos, Nothing, Nothing, Nothing) + + Updates the position, velocity and top of the listener: + + BASS_3DVECTOR position = new BASS_3DVECTOR(camera.RealPosition.x, camera.RealPosition.y, camera.RealPosition.z); + BASS_3DVECTOR direction = new BASS_3DVECTOR(camera.RealDirection.x, camera.RealDirection.y, camera.RealDirection.z); + BASS_3DVECTOR up = new BASS_3DVECTOR(-camera.RealUp.x, -camera.RealUp.y, -camera.RealUp.z); + + if (!Bass.BASS_Set3DPosition(position, velocity, direction, up)) + throw new AudioException("Could not set the 3d position of the listener", "listener", Bass.BASS_ErrorGetCode()); + + Bass.BASS_Apply3D(); + + + Dim position As New BASS_3DVECTOR(camera.RealPosition.x, camera.RealPosition.y, camera.RealPosition.z) + Dim direction As New BASS_3DVECTOR(camera.RealDirection.x, camera.RealDirection.y, camera.RealDirection.z) + Dim up As New BASS_3DVECTOR(-camera.RealUp.x, -camera.RealUp.y, -camera.RealUp.z) + + If Not Bass.BASS_Set3DPosition(position, velocity, direction, up) Then + Throw New AudioException("Could not set the 3d position of the listener", "listener", Bass.BASS_ErrorGetCode()) + End If + + Bass.BASS_Apply3D() + + + + + + + + + + + + + + + + + + Loads a WAV, AIFF, MP3, MP2, MP1, OGG or plugin supported sample. + This overload uses Unicode file names! A BASS_UNICODE flag will automatically be added. + + The file name to load the sample from. + File offset to load the sample from. + Data length... 0 = use all data up to the end of file. If length over-runs the end of the file, it'll automatically be lowered to the end of the file. + Maximum number of simultaneous playbacks... 1 (min) - 65535 (max)... use one of the BASS_SAMPLE_OVER flags to choose the override decider, in the case of there being no free channel available for playback (ie. the sample is already playing max times). + A combination of these flags (see ): + + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data (not really recommended for samples). WDM drivers are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_LOOPLooped? Note that only complete sample loops are allowed, you can't loop just a part of the sample. More fancy looping can be achieved by streaming the file. + BASS_SAMPLE_MONOConvert the sample (MP3/MP2/MP1 only) to mono, if it's not already. This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + BASS_SAMPLE_SOFTWAREForce the sample to not use hardware mixing. + BASS_SAMPLE_VAMrequires DirectX 7 or above: Enables the DX7 voice allocation and management features on the sample, which allows the sample to be played in software or hardware. This flag is ignored if the BASS_SAMPLE_SOFTWARE flag is also specified. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D samples must be mono. + BASS_SAMPLE_MUTEMAXMute the sample when it is at (or beyond) it's max distance (3D samples only). + BASS_SAMPLE_OVER_VOLOverride: the channel with the lowest volume is overriden. + BASS_SAMPLE_OVER_POSOverride: the longest playing channel is overriden. + BASS_SAMPLE_OVER_DISTOverride: the channel furthest away (from the listener) is overriden (3D samples only). + BASS_UNICODEfile is a Unicode (16-bit characters) filename (no need to set this for this overload). + + + If successful, the loaded sample's handle is returned, else 0 is returned. Use to get the error code. + + Additional format support is available via the plugin system (see ). + Unless the BASS_SAMPLE_SOFTWARE flag is used, the sample will use hardware mixing if hardware resources are available. Use to see if there are hardware mixing resources available, and which sample formats are supported by the hardware. + The BASS_SAMPLE_VAM flag allows a sample to be played by both hardware and software, with the decision made when the sample is played rather than when it's loaded. A sample's VAM options are set via . + To play a sample, first a channel must be obtained using , which can then be played using . + If you want to play a large or one-off sample, then it would probably be better to stream it instead with . + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILSample functions are not available when using the "no sound" device. + BASS_ERROR_ILLPARAM and/or is invalid. The must be specified when loading from memory. + BASS_ERROR_FILEOPENThe could not be opened. + BASS_ERROR_FILEFORMThe 's format is not recognised/supported. + BASS_ERROR_CODECThe file uses a codec that's not available/supported. This can apply to WAV and AIFF files, and also MP3 files when using the "MP3-free" BASS version. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the sample is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + The BASS_SAMPLE_VAM flag requires DirectX 7 (or above). Away from Windows, all mixing is done in software (by BASS), so the BASS_SAMPLE_SOFTWARE flag is unnecessary. + On Windows and Windows CE, ACM codecs are supported with compressed WAV files. On iOS and OSX, CoreAudio codecs are supported, adding support for any file formats that have a codec installed. + + + Play a sample with it's default settings: + + int sample = Bass.BASS_SampleLoad("test.wav", 0L, 0, 1, BASSFlag.BASS_DEFAULT); + int channel = Bass.BASS_SampleGetChannel(sample, false); // get a sample channel + Bass.BASS_ChannelPlay(channel, false); // play it + + + Dim sample As Integer = Bass.BASS_SampleLoad("test.wav", 0L.ToUInt32(), 0, 1, BASSFlag.BASS_DEFAULT) + Dim channel As Integer = Bass.BASS_SampleGetChannel(sample, False) ' get a sample channel + Bass.BASS_ChannelPlay(channel, False) ' play it + + + + + + + + + + + + + + + + + + Loads a WAV, AIFF, MP3, MP2, MP1, OGG or plugin supported sample. + This overload uses an unmanaged IntPtr and implements loading a sample from memory. + + An unmanaged IntPtr to the allocated memory block at which the sample data resides. + File offset to load the sample from (NOT used here!). + Data length. Should be set to the length of the data contained in memory. + Maximum number of simultaneous playbacks... 1 (min) - 65535 (max)... use one of the BASS_SAMPLE_OVER flags to choose the override decider, in the case of there being no free channel available for playback (ie. the sample is already playing max times). + A combination of these flags (see ): + + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data (not really recommended for samples). WDM drivers are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_LOOPLooped? Note that only complete sample loops are allowed, you can't loop just a part of the sample. More fancy looping can be achieved by streaming the file. + BASS_SAMPLE_MONOConvert the sample (MP3/MP2/MP1 only) to mono, if it's not already. This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + BASS_SAMPLE_SOFTWAREForce the sample to not use hardware mixing. + BASS_SAMPLE_VAMrequires DirectX 7 or above: Enables the DX7 voice allocation and management features on the sample, which allows the sample to be played in software or hardware. This flag is ignored if the BASS_SAMPLE_SOFTWARE flag is also specified. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D samples must be mono. + BASS_SAMPLE_MUTEMAXMute the sample when it is at (or beyond) it's max distance (3D samples only). + BASS_SAMPLE_OVER_VOLOverride: the channel with the lowest volume is overriden. + BASS_SAMPLE_OVER_POSOverride: the longest playing channel is overriden. + BASS_SAMPLE_OVER_DISTOverride: the channel furthest away (from the listener) is overriden (3D samples only). + + + If successful, the loaded sample's handle is returned, else 0 is returned. Use to get the error code. + + Additional format support is available via the plugin system (see ). + Unless the BASS_SAMPLE_SOFTWARE flag is used, the sample will use hardware mixing if hardware resources are available. Use to see if there are hardware mixing resources available, and which sample formats are supported by the hardware. + The BASS_SAMPLE_VAM flag allows a sample to be played by both hardware and software, with the decision made when the sample is played rather than when it's loaded. A sample's VAM options are set via . + To play a sample, first a channel must be obtained using , which can then be played using . + If you want to play a large or one-off sample, then it would probably be better to stream it instead with . + There is no need to pin the memory buffer for this method, since after loading a sample from memory, the memory can safely be discarded, as a copy is made. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILSample functions are not available when using the "no sound" device. + BASS_ERROR_ILLPARAM and/or is invalid. The must be specified when loading from memory. + BASS_ERROR_FILEOPENThe could not be opened. + BASS_ERROR_FILEFORMThe 's format is not recognised/supported. + BASS_ERROR_CODECThe file uses a codec that's not available/supported. This can apply to WAV and AIFF files, and also MP3 files when using the "MP3-free" BASS version. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the sample is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + The BASS_SAMPLE_VAM flag requires DirectX 7 (or above). Away from Windows, all mixing is done in software (by BASS), so the BASS_SAMPLE_SOFTWARE flag is unnecessary. + On Windows and Windows CE, ACM codecs are supported with compressed WAV files. On iOS and OSX, CoreAudio codecs are supported, adding support for any file formats that have a codec installed. + + + See for examples on how to load data from memory. + + + + + + + + + + + + + + + + + Loads a WAV, AIFF, MP3, MP2, MP1, OGG or plugin supported sample. + This overload uses an unmanaged IntPtr and implements loading a sample from memory. + + A managed byte[] containing the sample data to load. + File offset to load the sample from (NOT used here!). + Data length. Should be set to the length of the data contained in memory. + Maximum number of simultaneous playbacks... 1 (min) - 65535 (max)... use one of the BASS_SAMPLE_OVER flags to choose the override decider, in the case of there being no free channel available for playback (ie. the sample is already playing max times). + A combination of these flags (see ): + + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data (not really recommended for samples). WDM drivers are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_LOOPLooped? Note that only complete sample loops are allowed, you can't loop just a part of the sample. More fancy looping can be achieved by streaming the file. + BASS_SAMPLE_MONOConvert the sample (MP3/MP2/MP1 only) to mono, if it's not already. This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + BASS_SAMPLE_SOFTWAREForce the sample to not use hardware mixing. + BASS_SAMPLE_VAMrequires DirectX 7 or above: Enables the DX7 voice allocation and management features on the sample, which allows the sample to be played in software or hardware. This flag is ignored if the BASS_SAMPLE_SOFTWARE flag is also specified. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D samples must be mono. + BASS_SAMPLE_MUTEMAXMute the sample when it is at (or beyond) it's max distance (3D samples only). + BASS_SAMPLE_OVER_VOLOverride: the channel with the lowest volume is overriden. + BASS_SAMPLE_OVER_POSOverride: the longest playing channel is overriden. + BASS_SAMPLE_OVER_DISTOverride: the channel furthest away (from the listener) is overriden (3D samples only). + + + If successful, the loaded sample's handle is returned, else 0 is returned. Use to get the error code. + + Additional format support is available via the plugin system (see ). + Unless the BASS_SAMPLE_SOFTWARE flag is used, the sample will use hardware mixing if hardware resources are available. Use to see if there are hardware mixing resources available, and which sample formats are supported by the hardware. + The BASS_SAMPLE_VAM flag allows a sample to be played by both hardware and software, with the decision made when the sample is played rather than when it's loaded. A sample's VAM options are set via . + To play a sample, first a channel must be obtained using , which can then be played using . + If you want to play a large or one-off sample, then it would probably be better to stream it instead with . + There is no need to pin the memory buffer for this method, since BASS creates a copy of the data internally, + so the buffer provided will not be used anymore when the method returns. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILSample functions are not available when using the "no sound" device. + BASS_ERROR_ILLPARAM and/or is invalid. The must be specified when loading from memory. + BASS_ERROR_FILEOPENThe could not be opened. + BASS_ERROR_FILEFORMThe 's format is not recognised/supported. + BASS_ERROR_CODECThe file uses a codec that's not available/supported. This can apply to WAV and AIFF files, and also MP3 files when using the "MP3-free" BASS version. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the sample is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + The BASS_SAMPLE_VAM flag requires DirectX 7 (or above). Away from Windows, all mixing is done in software (by BASS), so the BASS_SAMPLE_SOFTWARE flag is unnecessary. + On Windows and Windows CE, ACM codecs are supported with compressed WAV files. On iOS and OSX, CoreAudio codecs are supported, adding support for any file formats that have a codec installed. + + + See for examples on how to load data from memory. + + + + + Initiates the creation of a user generated sample. + + The sample's length, in bytes. + The default sample rate. + The number of channels... 1 = mono, 2 = stereo, etc... More than stereo requires WDM drivers in Windows. + Maximum number of simultaneous playbacks... 1 (min) - 65535 (max)... use one of the BASS_SAMPLE_OVER flags to choose the override decider, in the case of there being no free channel available for playback (ie. the sample is already playing max times). + A combination of these flags (): + + BASS_SAMPLE_8BITSUse 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the sample is 16-bit. + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data (not really recommended for samples). WDM drivers are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_LOOPLooped? Note that only complete sample loops are allowed, you can't loop just a part of the sample. More fancy looping can be achieved via streaming. + BASS_SAMPLE_SOFTWAREForce the sample to not use hardware mixing. + BASS_SAMPLE_VAMrequires DirectX 7 or above: Enables the DX7 voice allocation and management features on the sample, which allows the sample to be played in software or hardware. This flag is ignored if the BASS_SAMPLE_SOFTWARE flag is also specified. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D samples must be mono (use BASS_SAMPLE_MONO). + BASS_SAMPLE_MUTEMAXMute the sample when it is at (or beyond) it's max distance (software 3D samples only). + BASS_SAMPLE_OVER_VOLOverride: the channel with the lowest volume is overriden. + BASS_SAMPLE_OVER_POSOverride: the longest playing channel is overriden. + BASS_SAMPLE_OVER_DISTOverride: the channel furthest away (from the listener) is overriden (3D samples only). + + + If successful, the new sample's handle is returned, else 0 is returned. Use to get the error code. + + The sample's initial content is undefined. should be used to set the sample's data. + Unless the BASS_SAMPLE_SOFTWARE flag is used, the sample will use hardware mixing if hardware resources are available. + Use to see if there are hardware mixing resources available, and which sample formats are supported by the hardware. + The BASS_SAMPLE_VAM flag allows a sample to be played by both hardware and software, with the decision made when the sample is played rather than when it's loaded. + A sample's VAM options are set via . + To play a sample, first a channel must be obtained using , which can then be played using . + If you want to play a large or one-off sample, then it would probably be better to stream it instead with . + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILSample functions are not available when using the "no sound" device. + BASS_ERROR_ILLPARAM is invalid.. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the sample is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + The BASS_SAMPLE_VAM flag requires DirectX 7 (or above). Away from Windows, all mixing is done in software (by BASS), so the BASS_SAMPLE_SOFTWARE flag is unnecessary. + + + Create a 440Hz sine-wave, 16-bit, mono: + + // create the sample + int sample = Bass.BASS_SampleCreate(256, 28160, 1, 1, + BASSFlag.BASS_SAMPLE_LOOP | BASSFlag.BASS_SAMPLE_OVER_POS ); + // the data buffer (256 byte = 128 Int16) + short[] data = new short[128]; + // create the sine wave + for (int a=0; a<128; a++) + data[a] = (short)(32767.0 * Math.Sin((double)a * 6.283185 / 64d)); + // set the sample's data + Bass.BASS_SampleSetData(sample, data); + // get a sample channel + int channel = Bass.BASS_SampleGetChannel(sample, false); + // play it + Bass.BASS_ChannelPlay(channel, false); + + + ' create the sample + Dim sample As Integer = Bass.BASS_SampleCreate(256, 28160, 1, 1, BASSFlag.BASS_SAMPLE_LOOP Or BASSFlag.BASS_SAMPLE_OVER_POS) + ' the data buffer (256 byte = 128 Int16) + Dim data(128 - 1) As Short + ' create the sine wave + Dim a As Integer + For a = 0 To 127 + data(a) = CShort(32767.0 * Math.Sin((CDbl(a) * 6.283185 / 64.0))) + Next a + ' set the sample's data + Bass.BASS_SampleSetData(sample, data) + ' get a sample channel + Dim channel As Integer = Bass.BASS_SampleGetChannel(sample, False) + ' play it + Bass.BASS_ChannelPlay(channel, False) + + + + + + Sets a sample's data. + + The sample handle. + Pointer to the data to set. + If successful, is returned, else is returned. Use to get the error code. + The required length and format of the data can be retrieved via . + A sample's data can be set at any time, including during playback. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + See . + + + + Sets a sample's data. + + The sample handle. + The array of float values representing the sample data to set. + If successful, is returned, else is returned. Use to get the error code. + The required length and format of the data can be retrieved via . + A sample's data can be set at any time, including during playback. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + See . + + + + Sets a sample's data. + + The sample handle. + The array of Int32 values representing the sample data to set (Caution: Int32=2xInt16, so this overload can e.g. be used to provide a stereo sample containing of two 16-bit values). + If successful, is returned, else is returned. Use to get the error code. + The required length and format of the data can be retrieved via . + A sample's data can be set at any time, including during playback. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + See . + + + + Sets a sample's data. + + The sample handle. + The array of Int16 values representing the sample data to set. + If successful, is returned, else is returned. Use to get the error code. + The required length and format of the data can be retrieved via . + A sample's data can be set at any time, including during playback. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + See . + + + + Sets a sample's data. + + The sample handle. + The array of byte values representing the sample data to set. + If successful, is returned, else is returned. Use to get the error code. + The required length and format of the data can be retrieved via . + A sample's data can be set at any time, including during playback. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + See . + + + + Retrieves a copy of a sample's data. + + The sample handle. + Pointer to a buffer to receive the data. + If successful, is returned, else is returned. Use to get the error code. + The buffer must be big enough to receive the sample's data, the size of which can be retrieved via . + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Retrieves a copy of a sample's data. + This overload uses a managed float[] to reference the buffer data as 32-bit! + SHOULD ONLY BE USED, if the sample was created with BASS_SAMPLE_FLOAT! + + The sample handle. + The array (float[]) to receive the data, use BASS_SAMPLE_FLOAT when creating the sample! + If successful, is returned, else is returned. Use to get the error code. + The buffer must be big enough to receive the sample's data, the size of which can be retrieved via . + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + BASS_SAMPLE info = Bass.BASS_SampleGetInfo(sample); + float[] buffer = new float[info.length/4]; + Bass.BASS_SampleGetData(sample, buffer); + + + Dim info As BASS_SAMPLE = Bass.BASS_SampleGetInfo(sample) + Dim buffer(info.length/4 - 1) As Single + Bass.BASS_SampleGetData(sample, buffer) + + + + + + Retrieves a copy of a sample's data. + This overload uses a managed int[] to reference the buffer data (Note: if we expect to receive 16-bit data, a single Int32 value will contain 2 x 16-bit, left and right channel)! + SHOULD ONLY BE USED, if the sample was created WITHOUT BASS_SAMPLE_FLOAT or BASS_SAMPLE_8BITS! + + The sample handle. + The array (int[]) to receive the data, e.g. when creating the sample with default setting, meaning 16-bit samples, an Int32 value contains 2 channels (left and right)! + If successful, is returned, else is returned. Use to get the error code. + The buffer must be big enough to receive the sample's data, the size of which can be retrieved via . + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Retrieves a copy of a sample's data. + This overload uses a managed short[] to reference the buffer data as 16-bit! + SHOULD ONLY BE USED, if the sample was created WITHOUT BASS_SAMPLE_FLOAT or BASS_SAMPLE_8BITS! + + The sample handle. + The array (short[]) to receive the data, do not use BASS_SAMPLE_FLOAT or BASS_SAMPLE_8BITS when creating the sample! + If successful, is returned, else is returned. Use to get the error code. + The buffer must be big enough to receive the sample's data, the size of which can be retrieved via . + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + BASS_SAMPLE info = Bass.BASS_SampleGetInfo(sample); + short[] buffer = new short[info.length/2]; + Bass.BASS_SampleGetData(sample, buffer); + + + Dim info As BASS_SAMPLE = Bass.BASS_SampleGetInfo(sample) + Dim buffer(info.length/2 - 1) As Short + Bass.BASS_SampleGetData(sample, buffer) + + + + + + Retrieves a copy of a sample's data. + This overload uses a managed byte[] to reference the buffer data as 8-bit! + SHOULD ONLY BE USED, if the sample was created with or BASS_SAMPLE_8BITS! + + The sample handle. + The array array (byte[]) to receive the data, use or BASS_SAMPLE_8BITS when creating the sample! + If successful, is returned, else is returned. Use to get the error code. + The buffer must be big enough to receive the sample's data, the size of which can be retrieved via . + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + BASS_SAMPLE info = Bass.BASS_SampleGetInfo(sample); + byte[] buffer = new byte[info.length]; + Bass.BASS_SampleGetData(sample, buffer); + + + Dim info As BASS_SAMPLE = Bass.BASS_SampleGetInfo(sample) + Dim buffer(info.length - 1) As Byte + Bass.BASS_SampleGetData(sample, buffer) + + + + + + Frees a sample's resources. + + The sample handle. + If successful, is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + Play a sample with it's default settings: + + int sample = Bass.BASS_SampleLoad("test.wav", 0L, 0, 1, BASSFlag.BASS_DEFAULT); + int channel = Bass.BASS_SampleGetChannel(sample, false); // get a sample channel + Bass.BASS_ChannelPlay(channel, false); // play it + ... + // when done + Bass.BASS_SampleFree(sample); + + + Dim sample As Integer = Bass.BASS_SampleLoad("test.wav", 0L.ToUInt32(), 0, 1, BASSFlag.BASS_DEFAULT) + Dim channel As Integer = Bass.BASS_SampleGetChannel(sample, False) ' get a sample channel + Bass.BASS_ChannelPlay(channel, False) ' play it + ... + ' when done + Bass.BASS_SampleFree(sample) + + + + + + Retrieves a sample's default attributes and other information. + + The sample handle. + An instance of the class to store the sample information at. + If successful, is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + BASS_SAMPLE info = new BASS_SAMPLE(); + bool ok = Bass.BASS_SampleGetInfo(sample, info); + + + Dim info As New BASS_SAMPLE() + Dim ok As Boolean = Bass.BASS_SampleGetInfo(sample, info) + + + + + + Retrieves a sample's default attributes and other information. + + The sample handle. + An instance of the class on success - else . + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + BASS_SAMPLE info = Bass.BASS_SampleGetInfo(sample); + + + Dim info As BASS_SAMPLE = Bass.BASS_SampleGetInfo(sample) + + + + + + Sets a sample's default attributes. + + The sample handle. + An instance of the class containing the sample information to set. + If successful, is returned, else is returned. Use to get the error code. + + Use this function and to edit a sample's default attributes. + Changing a sample's default attributes does not affect any existing channels, it only affects channels subsequently created via . + The exception is the VAM settings, changes to that apply to all the sample's channels at their next playback (). + Use and to change the attributes of an existing sample channel. + The sample's maximum number of simultaneous playbacks can be changed via the max member of the BASS_SAMPLE structure. If the new maximum is lower than the existing number of channels, the channels will remain existing until they are stopped. + The length, origres and chans members of the structure can't be modified - any changes are ignored. + The BASS_SAMPLE_8BITS, BASS_SAMPLE_MONO, BASS_SAMPLE_3D, BASS_SAMPLE_MUTEMAX, BASS_SAMPLE_SOFTWARE and BASS_SAMPLE_VAM flags also cannot be changed. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + Use one of the BASS_SAMPLE constructors to set the values: + + BASS_SAMPLE info = new BASS_SAMPLE(44100, 100, 0, ...); + bool ok = Bass.BASS_SampleSetInfo(sample, info); + + + Dim info As New BASS_SAMPLE(44100, 100, 0, ...) + Dim ok As Boolean = Bass.BASS_SampleSetInfo(sample, info) + + + + + + Creates/initializes a playback channel for a sample. + + Handle of the sample to play. + Do not recycle/override one of the sample's existing channels? + If successful, the handle of the new channel is returned, else 0 is returned. Use to get the error code. + + Use and to set a sample's default attributes, which are used when creating a channel. + After creation, a channel's attributes can be changed via , and . + should be called before starting playback of a 3D sample, even if you just want to use the default settings. + If a sample has a maximum number of simultaneous playbacks of 1 (the max parameter was 1 when calling or ), then the HCHANNEL handle returned will be identical to the HSAMPLE handle. + That means you can use the HSAMPLE handle with functions that usually require a HCHANNEL handle, but you must still call this function first to initialize the channel. + A sample channel is automatically freed when it's overridden by a new channel, or when stopped manually via , or . + If you wish to stop a channel and re-use it, it should be paused () instead of stopped. + Determining whether a channel still exists can be done by trying to use the handle in a function call, eg. . + When channel overriding has been enabled via a BASS_SAMPLE_OVER flag and there are multiple candidates for overriding (eg. with identical volume), the oldest of them will be chosen to make way for the new channel. + The new channel will have an initial state of being paused (BASS_ACTIVE_PAUSED). This prevents the channel being claimed by another call of this function before it has been played, unless it gets overridden due to a lack of free channels. + All of a sample's channels share the same sample data, and just have their own individual playback state information (volume/position/etc). + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid sample handle. + BASS_ERROR_NOCHANThe sample has no free channels... the maximum number of simultaneous playbacks has been reached, and no BASS_SAMPLE_OVER flag was specified for the sample or onlynew = . + BASS_ERROR_TIMEOUTThe sample's minimum time gap () has not yet passed since the last channel was created. + + + + + Play a sample with it's default settings: + + int sample = Bass.BASS_SampleLoad("test.wav", 0L, 0, 1, BASSFlag.BASS_DEFAULT); + int channel = Bass.BASS_SampleGetChannel(sample, false); // get a sample channel + Bass.BASS_ChannelPlay(channel, false); // play it + + + Dim sample As Integer = Bass.BASS_SampleLoad("test.wav", 0L.ToUInt32(), 0, 1, BASSFlag.BASS_DEFAULT) + Dim channel As Integer = Bass.BASS_SampleGetChannel(sample, False) ' get a sample channel + Bass.BASS_ChannelPlay(channel, False) ' play it + + + + + + Retrieves all a sample's existing channels. + + Handle of the sample. + The array (int[])to put the sample's channel handles in. The array should be the same size as the sample's max setting when the sample was created, which can be retrieved using . + can be used to just check how many channels exist. + If successful, the number of existing channels is returned, else -1 is returned. Use to get the error code. + For ease of use you might also use the second overload, which directly returns an integer array to get the channels directly. + If you need to determine whether a particular sample channel still exists, it is simplest to just try it in a function call, eg. . + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid sample handle. + + + + + Set the sample rate of all a sample's channels to 10000Hz: + + // get sample info for "max" value + BASS_SAMPLE info = Bass.BASS_SampleGetInfo(handle); + // allocate channels array + int[] chans = new int[info.max]; + // get the channels + int count = Bass.BASS_SampleGetChannels(handle, chans); + // go through them all and... + for (int a=0; a<count; a++) + { + // set the sample rate to 10000 + Bass.BASS_ChannelSetAttribute(chans[a], BASSAttribute.BASS_ATTRIB_FREQ, 10000f); + } + + + ' get sample info for "max" value + Dim info As BASS_SAMPLE = Bass.BASS_SampleGetInfo(handle) + ' allocate channels array + Dim chans(info.max) As Integer + ' get the channels + Dim count As Integer = Bass.BASS_SampleGetChannels(handle, hGC.AddrOfPinnedObject()) + ' go through them all and... + Dim a As Integer + For a = 0 To count - 1 + ' set the sample rate to 10000 + Bass.BASS_ChannelSetAttribute(chans(a), BASSAttribute.BASS_ATTRIB_FREQ, 10000F) + Next a + + + + + + Retrieves all a sample's existing channels. + + Handle of the sample. + If successful, the array of existing channels is returned (which might have zero elements), else is returned. Use to get the error code. + This overload only returns the existing channels in the array. + If you need to determine whether a particular sample channel still exists, it is simplest to just try it in a function call, eg. . + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid sample handle. + + + + + Set the sample rate of all a sample's channels to 10000hz: + + int[] chans = Bass.BASS_SampleGetChannels(handle); + if (chans != null) + { + // go through them all and... + for (int a=0; a<chans.Length; a++) + { + // set the sample rate to 10000 + Bass.BASS_ChannelSetAttribute(chans[a], BASSAttribute.BASS_ATTRIB_FREQ, 10000f); + } + } + + + Dim chans As Integer() = Bass.BASS_SampleGetChannels(handle) + If Not (chans Is Nothing) Then + ' go through them all and... + Dim a As Integer + For a = 0 To chans.Length - 1 + ' set the sample rate to 10000 + Bass.BASS_ChannelSetAttribute(chans(a), BASSAttribute.BASS_ATTRIB_FREQ, 10000F) + Next a + End If + + + + + + Retrieves the number of existing sample's channels. + + Handle of the sample. + If successful, the number of existing channels is returned, else -1 is returned. Use to get the error code. + If you need to determine whether a particular sample channel still exists, it is simplest to just try it in a function call, eg. . + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid sample handle. + + + + + + + Stops all instances of a sample. + + The sample handle. + If successful, is returned, else is returned. Use to get the error code. + If a sample is playing simultaneously multiple times, calling this function will stop them all, which is obviously simpler than calling multiple times. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid sample handle. + + + + + + + Creates a user sample stream. + + The default sample rate. The sample rate can be changed using . + The number of channels... 1 = mono, 2 = stereo, 4 = quadraphonic, 6 = 5.1, 8 = 7.1. More than stereo requires WDM drivers, and the SPEAKER flags are ignored. + Any combination of these flags (see ): + + BASS_SAMPLE_8BITSUse 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the stream is 16-bit. + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag. See Floating-point channels for more info. + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D streams must be mono (chans=1). The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_AUTOFREEAutomatically free the stream's resources when it has reached the end, or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + + + The user defined stream writing function (see ). + To create a DUMMY stream use the method. + To create a PUSH stream use the method. + + User instance data to pass to the callback function. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + Sample streams allow any sample data to be played through BASS, and are particularly useful for playing a large amount of sample data without requiring a large amount of memory. + If you wish to play a sample format that BASS does not support, then you can create a stream and decode the sample data into it. + BASS can automatically stream MP3, MP2, MP1, OGG, WAV and AIFF files, using , and also from HTTP and FTP servers, + using , allows streaming from other sources too. + However, the callback method must deliver PCM sample data as specified, so opening an MP3 file and just passing that file data will not work here. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + Away from Windows, all mixing is done in software (by BASS), so the BASS_SAMPLE_SOFTWARE flag is unnecessary. The BASS_SAMPLE_FX flag is also ignored. + + + A callback function to stream a file, in 44100hz 16-bit stereo: + + private STREAMPROC _myStreamCreate; // make it global, so that the GC can not remove it + private byte[] _data = null; // our local buffer + ... + _myStreamCreate = new STREAMPROC(MyFileProc); + FileStream fs = File.OpenRead("test.raw"); + int channel = Bass.BASS_StreamCreate(44100, 2, + BASSFlag.BASS_DEFAULT, _myStreamCreate, IntPtr.Zero); + Bass.BASS_ChannelPlay(channel, false); + ... + private int MyFileProc(int handle, IntPtr buffer, int length, IntPtr user) + { + // implementing the callback for BASS_StreamCreate... + // here we need to deliver PCM sample data + + // increase the data buffer as needed + if (_data == null || _data.Length < length) + _data = new byte[length]; + + int bytesread = _fs.Read( _data, 0, length ); + Marshal.Copy( _data, 0, buffer, bytesread ); + if ( bytesread < length ) + { + // set indicator flag + bytesread |= (int)BASSStreamProc.BASS_STREAMPROC_END; + _fs.Close(); + } + return bytesread; + } + + + Private _myStreamCreate As STREAMPROC ' make it global, so that the GC can not remove it + Private _data As Byte() = Nothing ' our local buffer + ... + _myStreamCreate = New STREAMPROC(AddressOf MyFileProc) + Dim fs As FileStream = File.OpenRead("test.raw") + Dim channel As Integer = Bass.BASS_StreamCreate(44100, 2, + BASSFlag.BASS_DEFAULT, _myStreamCreate, IntPtr.Zero) + Bass.BASS_ChannelPlay(channel, False) + ... + Private Function MyFileProc(ByVal handle As Integer, ByVal buffer As IntPtr, + ByVal length As Integer, ByVal user As IntPtr) As Integer + ' implementing the callback for BASS_StreamCreate... + ' here we need to deliver PCM sample data + + ' increase the data buffer as needed + If _data = Nothing OrElse _data.Length < length Then + _data = New Byte(length) {} + End If + + Dim bytesread As Integer = _fs.Read(_data, 0, length) + Marshal.Copy(_data, 0, buffer, bytesread) + If bytesread < length Then + bytesread = bytesread Or CInt(BASSStreamProc.BASS_STREAMPROC_END) ' set indicator flag + _fs.Close() + EndIf + Return bytesread + End Function + + + + + + + + + + + + + + + + + Creates a "dummy" stream. + + The default sample rate. The sample rate can be changed using . + The number of channels... 1 = mono, 2 = stereo, 4 = quadraphonic, 6 = 5.1, 8 = 7.1. More than stereo requires WDM drivers, and the SPEAKER flags are ignored. + Any combination of these flags (see ): + + BASS_SAMPLE_8BITSUse 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the stream is 16-bit. + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag. See Floating-point channels for more info. + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D streams must be mono (chans=1). The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_AUTOFREEAutomatically free the stream's resources when it has reached the end, or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + + + One of the following (see ): + + STREAMPROC_DUMMYCreate a "dummy" stream. A dummy stream doesn't have any sample data of its own, but a decoding dummy stream (with flag) can be used to apply DSP/FX processing to any sample data, by setting DSP/FX on the stream and feeding the data through . The dummy stream should have the same sample format as the data being fed through it. + STREAMPROC_PUSHCreate a "push" stream. Instead of BASS pulling data from a STREAMPROC function, data is pushed to BASS via . + + + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + A dummy stream doesn't have any sample data of its own, but a decoding dummy stream (with BASS_STREAM_DECODE flag) can be used to apply DSP/FX processing to any sample data, + by setting DSP/FX on the stream and feeding the data through . + The dummy stream should have the same sample format as the data being fed through it. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + Away from Windows, all mixing is done in software (by BASS), so the BASS_SAMPLE_SOFTWARE flag is unnecessary. The BASS_SAMPLE_FX flag is also ignored. + + + + + Creates a "dummy" stream. + + The default sample rate. The sample rate can be changed using . + The number of channels... 1 = mono, 2 = stereo, 4 = quadraphonic, 6 = 5.1, 8 = 7.1. More than stereo requires WDM drivers, and the SPEAKER flags are ignored. + Any combination of these flags (see ): + + BASS_SAMPLE_8BITSUse 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the stream is 16-bit. + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag. See Floating-point channels for more info. + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D streams must be mono (chans=1). The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_AUTOFREEAutomatically free the stream's resources when it has reached the end, or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + + + User instance data to pass to the callback function. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + A dummy stream doesn't have any sample data of its own, but a decoding dummy stream (with BASS_STREAM_DECODE flag) can be used to apply DSP/FX processing to any sample data, + by setting DSP/FX on the stream and feeding the data through . + The dummy stream should have the same sample format as the data being fed through it. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + Away from Windows, all mixing is done in software (by BASS), so the BASS_SAMPLE_SOFTWARE flag is unnecessary. The BASS_SAMPLE_FX flag is also ignored. + + + + + Creates a "push" stream. + + The default sample rate. The sample rate can be changed using . + The number of channels... 1 = mono, 2 = stereo, 4 = quadraphonic, 6 = 5.1, 8 = 7.1. More than stereo requires WDM drivers, and the SPEAKER flags are ignored. + Any combination of these flags (see ): + + BASS_SAMPLE_8BITSUse 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the stream is 16-bit. + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag. See Floating-point channels for more info. + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D streams must be mono (chans=1). The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_AUTOFREEAutomatically free the stream's resources when it has reached the end, or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + + + User instance data to pass to the callback function. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + Instead of BASS pulling data from a function, data is pushed to BASS via . + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + Away from Windows, all mixing is done in software (by BASS), so the BASS_SAMPLE_SOFTWARE flag is unnecessary. The BASS_SAMPLE_FX flag is also ignored. + + + Creating a stream duplicate: + + private DSPPROC _dupCallback; + ... + // create stream on device 1 + Bass.BASS_SetDevice(1); + int orig = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_SAMPLE_LOOP); + Bass.BASS_ChannelPlay(orig, false); + ... + // create a clone on device 2 + BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(stream); + Bass.BASS_SetDevice(2); + int clone = Bass.BASS_StreamCreatePush(info.freq, info.chans, info.flags, IntPtr.Zero); + // pause source stream to synchonise buffer contents + Bass.BASS_ChannelPause(stream); + int c = Bass.BASS_ChannelGetData(stream, IntPtr.Zero, (int)BASSData.BASS_DATA_AVAILABLE); + byte[] buf = new byte[c]; + Bass.BASS_ChannelGetData(stream, buf, c); + Bass.BASS_StreamPutData(clone, buf, c); + // set DSP to copy new data from source stream + _dupCallback = new DSPPROC(DupDSP); + Bass.BASS_ChannelSetDSP(orig, _dupCallback, new IntPtr(clone), 0); + Bass.BASS_ChannelPlay(orig, false); // resume source + Bass.BASS_ChannelPlay(clone, false); // play clone + ... + private void DupDSP(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + Bass.BASS_StreamPutData(user.ToInt32(), buffer, length); + } + + + Private _dupCallback As DSPPROC + ... + ' create stream on device 1 + Bass.BASS_SetDevice(1) + Dim orig As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_SAMPLE_LOOP) + Bass.BASS_ChannelPlay(orig, False) + ... + ' create a clone on device 2 + Dim info As BASS_CHANNELINFO = Bass.BASS_ChannelGetInfo(stream) + Bass.BASS_SetDevice(2) + Dim clone As Integer = Bass.BASS_StreamCreatePush(info.freq, info.chans, info.flags, IntPtr.Zero) + ' pause source stream to synchonise buffer contents + Bass.BASS_ChannelPause(stream) + Dim c As Integer = Bass.BASS_ChannelGetData(stream, IntPtr.Zero, CInt(BASSData.BASS_DATA_AVAILABLE)) + Dim buf(c) As Byte + Bass.BASS_ChannelGetData(stream, buf, c) + Bass.BASS_StreamPutData(clone, buf, c) + ' set DSP to copy new data from source stream + _dupCallback = New DSPPROC(DupDSP) + Bass.BASS_ChannelSetDSP(orig, _dupCallback, New IntPtr(clone), 0) + Bass.BASS_ChannelPlay(orig, False) ' resume source + Bass.BASS_ChannelPlay(clone, False) ' play clone + ... + Private Sub DupDSP(handle As Integer, channel As Integer, + buffer As IntPtr, length As Integer, user As IntPtr) + Bass.BASS_StreamPutData(user.ToInt32(), buffer, length) + End Sub + + + + + + Creates a sample stream from an MP3, MP2, MP1, OGG, WAV, AIFF or plugin supported file via user callback functions. + + File system to use (one of the ): + + STREAMFILE_NOBUFFERUnbuffered. + STREAMFILE_BUFFERBuffered. + STREAMFILE_BUFFERPUSHBuffered, with the data pushed to BASS via . + + + Any combination of these flags (see ): + + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_MONODecode/play the stream (MP3/MP2/MP1 only) in mono, reducing the CPU usage (if it was originally stereo). This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D streams must be mono. The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_LOOPLoop the file. This flag can be toggled at any time using . This flag is ignored when streaming in blocks (BASS_STREAM_BLOCK). + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_PRESCANEnable pin-point accurate seeking (to the exact byte) on the MP3/MP2/MP1 stream. This also increases the time taken to create the stream, due to the entire file being pre-scanned for the seek points. This flag is ignored with "buffered" streams (buffered=). + BASS_STREAM_RESTRATERestrict the download rate of the file to the rate required to sustain playback. If this flag is not used, then the file will be downloaded as quickly as possible. This flag has no effect on "unbuffered" streams (buffered=). + BASS_STREAM_BLOCKDownload and play the file in smaller chunks. Uses a lot less memory than otherwise, but it's not possible to seek or loop the stream - once it's ended, the file must be opened again to play it again. This flag will automatically be applied when the file length is unknown. This flag also has the effect of resticting the download rate. This flag has no effect on "unbuffered" streams (buffered=). + BASS_STREAM_AUTOFREEAutomatically free the stream when it ends. This allows you to stream a file and forget about it, as BASS will automatically free the stream's resources when it has reached the end or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + + + The user defined file function (see ). + User instance data to pass to the callback functions. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + The buffered file system (STREAMFILE_BUFFER) is what is used by . As the name suggests, data from the file is buffered so that it's readily available for decoding - BASS creates a thread dedicated to "downloading" the data. This is ideal for when the data is coming from a source that has high latency, like the internet. It's not possible to seek in buffered file streams, until the download has reached the requested position - it's not possible to seek at all if it's being streamed in blocks. + The push buffered file system (STREAMFILE_BUFFERPUSH) is the same, except that instead of the file data being pulled from the function in a "download" thread, the data is pushed to BASS via . A function is still required, to get the initial data used in the creation of the stream (see example below). + The unbuffered file system (STREAMFILE_NOBUFFER) is what is used by . In this system, BASS does not do any intermediate buffering - it simply requests data from the file as and when it needs it. This means that reading () must be quick, otherwise the decoding will be delayed and playback buffer underruns (old data repeated) are a possibility. It's not so important for seeking () to be fast, as that is generally not required during decoding, except when looping a file. + In all cases, BASS will automatically stall playback of the stream when insufficient data is available, and resume it when enough data does become available. + A copy is made of the procs callback function table, so it does not have to persist beyond this function call. + This means it is not required to pin the instance, but it is still required to keep a reference as long as BASS uses the callback delegates in order to prevent the callbacks from being garbage collected. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_ILLPARAM is not valid. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_CODECThe file uses a codec that's not available/supported. This can apply to WAV and AIFF files, and also MP3 files when using the "MP3-free" BASS version. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + Away from Windows, all mixing is done in software (by BASS), so the BASS_SAMPLE_SOFTWARE flag is unnecessary. The BASS_SAMPLE_FX flag is also ignored. + On Windows and Windows CE, ACM codecs are supported with compressed WAV files. Media Foundation codecs are also supported on Windows 7 and updated versions of Vista, including support for AAC/MP4 and WMA. On iOS and OSX, CoreAudio codecs are supported, adding support for any file formats that have a codec installed. Media Foundation and CoreAudio codecs are only tried after the built-in decoders and any plugins have rejected the file. + + STREAMFILE_BUFFERPUSH: + The first thing to note is that needs a stream handle. You don't have that until the call returns, + so some other way is needed for BASS to get the inital file data that it uses to detect the format/etc. That other way is the FILEREADPROC. + After the stream has been created, the FILEREADPROC is never called again, and the remaining file data is fed to the stream via . + E.g. a function receiving the data from the Internet would need to buffer the received data until the stream has been created, at which point it can start using instead. + The FILEREADPROC would read data from that buffer, and wait for the data to arrive if necessary. After the stream has been created, any buffered data that's remaining should be fed to the stream, before starting to feed newly arriving data. + You'll need some synchronization (eg. a mutex) to enforce that order of things. Something like this (pseudo-code): + + void Connect() + { + bufferobj = new Buffer(); + stream = BASS_StreamCreateFileUser(STREAMFILE_BUFFERPUSH, ...); + lock + { + BASS_StreamPutData(stream, ...); // feed remaining buffered data + bufferobj = NULL; // don't need the buffer anymore + } + } + + void OnReceiveData(pointer buffer, int length) + { + lock + { + if (bufferobj) + bufferobj.Write(buffer, length); + else + BASS_StreamPutData(stream, buffer, length); + } + } + + int FileReadProc(pointer buffer, int length, pointer user) + { + int todo = length; + while (TRUE) + { + lock + { + done = bufferobj.Read(buffer, todo); + } + buffer += done; // move pointer + todo -= done; + if (todo == 0) + break; + if (!bufferobj.WaitForData(timeout)) // wait for more data + break; // timed-out (or perhaps EOF) + } + return length - todo; + } + + + See . + + + + Only used internal! See the file overload of for details! + + Needs to be set to + The file name to open + Set to 0 to start the stream from the beginning + Data length... 0 = use all data + See for possible flags + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + + + Creates a sample stream from an MP3, MP2, MP1, OGG, WAV, AIFF or plugin supported file. + This overload implements Unicode filenames. The BASS_UNICODE flag will be added automatically, since all .Net strings are always unicode. + + Filename for which a stream should be created. + File offset to begin streaming from. + Data length... 0 = use all data up to the end of the file. + Any combination of these flags : + + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_MONODecode/play the stream (MP3/MP2/MP1 only) in mono, reducing the CPU usage (if it was originally stereo). This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D streams must be mono. The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_LOOPLoop the file. This flag can be toggled at any time using . + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_PRESCANEnable pin-point accurate seeking (to the exact byte) on the MP3/MP2/MP1 stream. This also increases the time taken to create the stream, due to the entire file being pre-scanned for the seek points. + BASS_STREAM_AUTOFREEAutomatically free the stream when it ends. This allows you to stream a file and forget about it, as BASS will automatically free the stream's resources when it has reached the end or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + BASS_UNICODEfile is a Unicode (16-bit characters) filename (automatically set with this overload). + + + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + BASS has built-in support for MPEG, OGG, WAV and AIFF files. Support for additional formats is available via add-ons, which can be downloaded from the BASS website: www.un4seen.com. + MPEG 1.0, 2.0 and 2.5 layer 3 (MP3) files are supported, layers 1 (MP1) and 2 (MP2) are also supported. Standard RIFF and RF64 WAV files are supported, with the sample data in a PCM format or compressed with an ACM codec, but the codec is required to be installed on the user's system for the WAV to be decoded. So you should either distribute the codec with your software, or use a codec that comes with Windows (eg. Microsoft ADPCM). All PCM formats from 8 to 32-bit are supported in WAV and AIFF files, but the output will be restricted to 16-bit unless the BASS_SAMPLE_FLOAT flag is used. 64-bit floating-point WAV and AIFF files are also supported, but are rendered in 16-bit or 32-bit floating-point depending on the flags. + The file's original resolution is available via . + Multi-channel (ie. more than stereo) OGG, WAV and AIFF files are supported. + Use to retrieve information on the format (sample rate, resolution, channels) of the stream. The playback length of the stream can be retrieved using . + If length = 0 (use all data up to the end of the file), and the file length increases after creating the stream (ie. the file is still being written), then BASS will play the extra data too, but the length returned by will not be updated until the end is reached. The return values will be updated during playback of the extra data though. + To stream a file from the internet, use . To stream from other locations, see . + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_ILLPARAM is not valid. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_CODECThe file uses a codec that's not available/supported. This can apply to WAV and AIFF files, and also MP3 files when using the "MP3-free" BASS version. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + Away from Windows, all mixing is done in software (by BASS), so the BASS_SAMPLE_SOFTWARE flag is unnecessary. The BASS_SAMPLE_FX flag is also ignored. + On Windows and Windows CE, ACM codecs are supported with compressed WAV files. Media Foundation codecs are also supported on Windows 7 and updated versions of Vista, including support for AAC/MP4 and WMA. On iOS and OSX, CoreAudio codecs are supported, adding support for any file formats that have a codec installed. Media Foundation and CoreAudio codecs are only tried after the built-in decoders and any plugins have rejected the file. + + + The following example demonstrates how to stream from a file (floating-point): + + // Init Bass + Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero); + // create the stream + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, + BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_PRESCAN); + if (stream != 0 && Bass.BASS_ChannelPlay(stream, false) ) + { + // playing + } + else + { + Console.WriteLine("Error={0}", Bass.BASS_ErrorGetCode()); + } + + + ' Init Bass + Bass.BASS_Init(- 1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) + ' create the stream + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, + BASSFlag.BASS_SAMPLE_FLOAT Or BASSFlag.BASS_STREAM_PRESCAN) + If stream <> 0 AndAlso Bass.BASS_ChannelPlay(stream, False) Then + ' playing + Else + Console.WriteLine("Error={0}", Bass.BASS_ErrorGetCode()) + End If + + + + + + Only used internal! See the memory overload of for details! + + Needs to be set to + The IntPtr to the unmananged buffer containing the stream data + Set to 0 to start the stream from the beginning + Needs to be set to the total length of the buffer data + See for possible flags + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + + + Creates a sample stream from an MP3, MP2, MP1, OGG, WAV, AIFF or plugin supported memory IntPtr. + This overload implements streaming from memory. + + An unmanaged pointer to the memory location as an IntPtr. + Offset to begin streaming from (unused for memory streams, set to 0). + Data length (needs to be set to the length of the memory stream in bytes which should be played). + Any combination of these flags , needs to casted into an (int) because we needed another method signature here. + + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_MONODecode/play the stream (MP3/MP2/MP1 only) in mono, reducing the CPU usage (if it was originally stereo). This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D streams must be mono. The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_LOOPLoop the file. This flag can be toggled at any time using . + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_PRESCANEnable pin-point accurate seeking (to the exact byte) on the MP3/MP2/MP1 stream. This also increases the time taken to create the stream, due to the entire file being pre-scanned for the seek points. + BASS_STREAM_AUTOFREEAutomatically free the stream when it ends. This allows you to stream a file and forget about it, as BASS will automatically free the stream's resources when it has reached the end or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + + + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + BASS has built-in support for MPEG, OGG, WAV and AIFF files. Support for additional formats is available via add-ons, which can be downloaded from the BASS website: www.un4seen.com. + MPEG 1.0, 2.0 and 2.5 layer 3 (MP3) files are supported, layers 1 (MP1) and 2 (MP2) are also supported. Standard RIFF and RF64 WAV files are supported, with the sample data in a PCM format or compressed with an ACM codec, but the codec is required to be installed on the user's system for the WAV to be decoded. So you should either distribute the codec with your software, or use a codec that comes with Windows (eg. Microsoft ADPCM). All PCM formats from 8 to 32-bit are supported in WAV and AIFF files, but the output will be restricted to 16-bit unless the BASS_SAMPLE_FLOAT flag is used. 64-bit floating-point WAV and AIFF files are also supported, but are rendered in 16-bit or 32-bit floating-point depending on the flags. The file's original resolution is available via . + Multi-channel (ie. more than stereo) OGG, WAV and AIFF files are supported. + Use to retrieve information on the format (sample rate, resolution, channels) of the stream. The playback length of the stream can be retrieved using . + If length = 0 (use all data up to the end of the file), and the file length increases after creating the stream (ie. the file is still being written), then BASS will play the extra data too, but the length returned by will not be updated until the end is reached. The return values will be updated during playback of the extra data though. + When streaming from memory, the memory must not be freed before the stream is freed. There may be exceptions to that with some add-ons (see the documentation). + To stream a file from the internet, use . To stream from other locations, see . + Don't forget to pin your memory object when using this overload. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_ILLPARAMThe must be specified when streaming from memory. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_CODECThe file uses a codec that's not available/supported. This can apply to WAV and AIFF files, and also MP3 files when using the "MP3-free" BASS version. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + Away from Windows, all mixing is done in software (by BASS), so the BASS_SAMPLE_SOFTWARE flag is unnecessary. The BASS_SAMPLE_FX flag is also ignored. + On Windows and Windows CE, ACM codecs are supported with compressed WAV files. Media Foundation codecs are also supported on Windows 7 and updated versions of Vista, including support for AAC/MP4 and WMA. On iOS and OSX, CoreAudio codecs are supported, adding support for any file formats that have a codec installed. Media Foundation and CoreAudio codecs are only tried after the built-in decoders and any plugins have rejected the file. + + + The following example demontrates how to stream from memory: + + private GCHandle _hGCFile; + ... + // open a file + FileStream fs = File.OpenRead( "test.mp3" ); + // get the legth of the file + long length = fs.Length; + // create the buffer which will keep the file in memory + byte[] buffer = new byte[length]; + // read the file into the buffer + fs.Read(buffer, 0, (int)length); + // buffer is filled, file can be closed + fs.Close(); + + // now create a pinned handle, so that the Garbage Collector will not move this object + _hGCFile = GCHandle.Alloc( buffer, GCHandleType.Pinned ); + // create the stream (AddrOfPinnedObject delivers the necessary IntPtr) + int stream = Bass.BASS_StreamCreateFile(_hGCFile.AddrOfPinnedObject(), + 0L, length, BASSFlag.BASS_SAMPLE_FLOAT); + + if (stream != 0 && Bass.BASS_ChannelPlay(stream, false) ) + { + // playing... + } + else + { + Console.WriteLine("Error = {0}", Bass.BASS_ErrorGetCode()); + } + ... + // when playback has ended and the pinned object is not needed anymore, + // we need to free the handle! + // Note: calling this method to early will crash the application, + // since the buffer would be stolen from BASS while still playing! + _hGCFile.Free(); + + + Private _hGCFile As GCHandle + ... + ' open a file + Dim fs As FileStream = File.OpenRead("test.mp3") + ' get the legth of the file + Dim length As Long = fs.Length + ' create the buffer which will keep the file in memory + Dim buffer(length - 1) As Byte + ' read the file into the buffer + fs.Read(buffer, 0, length) + ' buffer is filled, file can be closed + fs.Close() + + ' now create a pinned handle, so that the Garbage Collector will not move this object + _hGCFile = GCHandle.Alloc(buffer, GCHandleType.Pinned) + ' create the stream (AddrOfPinnedObject delivers the necessary IntPtr) + Dim stream As Integer = Bass.BASS_StreamCreateFile(_hGCFile.AddrOfPinnedObject(), + 0L, length, BASSFlag.BASS_SAMPLE_FLOAT) + + If stream <> 0 AndAlso Bass.BASS_ChannelPlay(stream, False) Then + ' playing... + Else + Console.WriteLine("Error = {0}", Bass.BASS_ErrorGetCode()) + End If + ... + ' when playback has ended and the pinned object is not needed anymore, + ' we need to free the handle! + ' Note: calling this method to early will crash the application, + ' since the buffer would be stolen from BASS while still playing! + _hGCFile.Free() + + + + + + + + + + + + + + + + + + + + + + + + + + + + Creates a sample stream from an MP3, MP2, MP1, OGG, WAV, AIFF or plugin supported file on the internet, optionally receiving the downloaded data in a callback. + + URL of the file to stream. Should begin with "http://" or "ftp://", or another add-on supported protocol. + File position to start streaming from. This is ignored by some servers, specifically when the file length is unknown, for example a Shout/Icecast server. + Any combination of these flags (see ): + + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_MONODecode/play the stream (MP3/MP2/MP1 only) in mono, reducing the CPU usage (if it was originally stereo). This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + BASS_SAMPLE_SOFTWAREForce the stream to not use hardware mixing. + BASS_SAMPLE_3DUse 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D streams must be mono. The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_LOOPLoop the file. This flag can be toggled at any time using . This flag is ignored when streaming in blocks (BASS_STREAM_BLOCK). + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the stream. + BASS_STREAM_RESTRATERestrict the download rate of the file to the rate required to sustain playback. If this flag is not used, then the file will be downloaded as quickly as the user's internet connection allows. + BASS_STREAM_BLOCKDownload and play the file in smaller chunks. Uses a lot less memory than otherwise, but it's not possible to seek or loop the stream - once it's ended, the file must be opened again to play it again. This flag will automatically be applied when the file length is unknown, for example with Shout/Icecast streams. This flag also has the effect of resticting the download rate. + BASS_STREAM_STATUSPass status info (HTTP/ICY tags) from the server to the callback during connection. This can be useful to determine the reason for a failure. + BASS_STREAM_AUTOFREEAutomatically free the stream when it ends. This allows you to stream a file and forget about it, as BASS will automatically free the stream's resources when it has reached the end or when (or ) is called. + BASS_STREAM_DECODEDecode the sample data, without outputting it. Use to retrieve decoded sample data. The BASS_SAMPLE_SOFTWARE, BASS_SAMPLE_3D, BASS_SAMPLE_FX, BASS_STREAM_AUTOFREE and SPEAKER flags can not be used together with this flag. + BASS_SPEAKER_xxxSpeaker assignment flags. + + + Callback function to receive the file as it is downloaded... = no callback. + User instance data to pass to the callback function. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + + Use to retrieve information on the format (sample rate, resolution, channels) of the stream. The playback length of the stream can be retrieved using . + When playing the stream, BASS will stall the playback if there is insufficient data to continue playing. Playback will automatically be resumed when sufficient data has been downloaded. can be used to check if the playback is stalled, and the progress of the file download can be checked with . + When streaming in blocks (BASS_STREAM_BLOCK flag), be careful not to stop/pause the stream for too long, otherwise the connection may timeout due to there being no activity and the stream will end prematurely. + When streaming from Shoutcast servers, metadata (track titles) may be sent by the server. The data can be retrieved with . A sync can also be set (using ) so that you are informed when metadata is received. + When using an , the file length returned by can be used to check that it was successful by comparing it with the original file length. Another way to check is to inspect the HTTP headers retrieved with . + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILOnly decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE flag is also unavailable to decoding channels. + BASS_ERROR_NONETNo internet connection could be opened. Can be caused by a bad proxy setting. + BASS_ERROR_ILLPARAM is not a valid URL. + BASS_ERROR_TIMEOUTThe server did not respond to the request within the timeout period, as set with the BASS_CONFIG_NET_TIMEOUT config option. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_CODECThe file uses a codec that's not available/supported. This can apply to WAV and AIFF files, and also MP3 files when using the "MP3-free" BASS version. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + Away from Windows, all mixing is done in software (by BASS), so the BASS_SAMPLE_SOFTWARE flag is unnecessary. The BASS_SAMPLE_FX flag is also ignored. + On Windows and Windows CE, ACM codecs are supported with compressed WAV files. Media Foundation codecs are also supported on Windows 7 and updated versions of Vista, including support for AAC/MP4 and WMA. On iOS and OSX, CoreAudio codecs are supported, adding support for any file formats that have a codec installed. Media Foundation and CoreAudio codecs are only tried after the built-in decoders and any plugins have rejected the file. + HTTPS is not supported on Linux. + + + + Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero); + int channel = Bass.BASS_StreamCreateURL("http://someurl.com:8000", 0, + BASSFlag.BASS_DEFAULT, null, IntPtr.Zero); + Bass.BASS_ChannelPlay(channel, false); + + + Bass.BASS_Init(- 1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) + Dim channel As Integer = Bass.BASS_StreamCreateURL("http://someurl.com:8000", 0, + BASSFlag.BASS_DEFAULT, Nothing, IntPtr.Zero) + Bass.BASS_ChannelPlay(channel, False) + + + + + + Retrieves the decoding/download/end position of a file stream. + + The stream's handle. + The file position to retrieve. One of the following (): + + BASS_FILEPOS_CURRENTPosition that is to be decoded for playback next. This will be a bit ahead of the position actually being heard due to buffering. + BASS_FILEPOS_ENDEnd of the file, in other words the file length. When streaming in blocks, the file length is unknown, so the download buffer length is returned instead. + BASS_FILEPOS_STARTStart of stream data in the file. + BASS_FILEPOS_DOWNLOADDownload progress of an internet file stream or "buffered" user file stream. + BASS_FILEPOS_CONNECTEDInternet file stream or "buffered" user file stream is still connected? 0 = no, 1 = yes. + BASS_FILEPOS_BUFFERThe amount of data in the buffer of an internet file stream or "buffered" user file stream. Unless streaming in blocks, this is the same as BASS_FILEPOS_DOWNLOAD. + + Other modes may be supported by add-ons, see the documentation. + + If succesful, then the requested file position is returned, else -1 is returned. Use to get the error code. + + ID3 tags (both v1 and v2) and WAVE headers, as well as any other rubbish at the start of the file, are excluded from the calculations of this function. + This is useful for average bitrate calculations, but it means that the BASS_FILEPOS_CURRENT position may not be the actual file position - the BASS_FILEPOS_START position can be added to it to get the actual file position. + It's unwise to use this function (with mode = BASS_FILEPOS_CURRENT) for syncing purposes because it returns the position that's being decoded, not the position that's being heard. + Use for syncing instead. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTFILEThe stream is not a file stream. + BASS_ERROR_NOTAVAILThe requested file position/status is not available. + + + + + Get the percentage downloaded of an internet file stream, + or the buffering progress when streaming in blocks: + + float progress; + // file length + int len = Bass.BASS_StreamGetFilePosition(stream, BASSStreamFilePosition.BASS_FILEPOS_END); + // download progress + int down = Bass.BASS_StreamGetFilePosition(stream, BASSStreamFilePosition.BASS_FILEPOS_DOWNLOAD); + // get channel info + BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(stream); + // streaming in blocks? + if (info.flags & BASSFlag.BASS_STREAM_BLOCK != BASSFlag.BASS_DEFAULT) + { + // decode position + int dec = BASS_StreamGetFilePosition(stream, BASSStreamFilePosition.BASS_FILEPOS_CURRENT); + // percentage of buffer used + progress = (down-dec)*100f / len; + if (progress > 100) + progress = 100; // restrict to 100 (can be higher) + } + else + { + // percentage of file downloaded + progress = down*100f / len; + } + + + Dim progress As Single + ' file length + Dim len As Integer = Bass.BASS_StreamGetFilePosition(stream, BASSStreamFilePosition.BASS_FILEPOS_END) + ' download progress + Dim down As Integer = Bass.BASS_StreamGetFilePosition(stream, BASSStreamFilePosition.BASS_FILEPOS_DOWNLOAD) + ' get channel info + Dim info As BASS_CHANNELINFO = Bass.BASS_ChannelGetInfo(stream) + ' streaming in blocks? + If info.flags And BASSFlag.BASS_STREAM_BLOCK <> BASSFlag.BASS_DEFAULT Then + ' decode position + Dim dec As Integer = BASS_StreamGetFilePosition(stream, BASSStreamFilePosition.BASS_FILEPOS_CURRENT) + ' percentage of buffer used + progress =(down - dec) * 100F / len + If progress > 100 Then + progress = 100 ' restrict to 100 (can be higher) + End If + Else + ' percentage of file downloaded + progress = down * 100F / len + End If + + Get the average bitrate of a file: + + // playback duration + double time = Bass.BASS_ChannelBytes2Seconds(stream, Bass.BASS_ChannelGetLength(stream)); + // file length + long len = Bass.BASS_StreamGetFilePosition(stream, BASSStreamFilePosition.BASS_FILEPOS_END); + // bitrate (kbps) + int bitrate = (int)(len/(125*time)+0.5d); + + + ' playback duration + Dim time As Double = Bass.BASS_ChannelBytes2Seconds(stream, Bass.BASS_ChannelGetLength(stream)) + ' file length + Dim len As Long = Bass.BASS_StreamGetFilePosition(stream, BASSStreamFilePosition.BASS_FILEPOS_END) + ' bitrate (kbps) + Dim bitrate As Integer = CInt(len /(125 * time) + 0.5) + + + + + + Frees a sample stream's resources, including any SYNC/DSP/FX it has. + + The stream handle. + If successful, is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + + Adds sample data to a "push" stream. + + The stream handle (as created with ). + Pointer to the sample data ( = allocate space in the queue buffer so that there is at least length bytes of free space). + The amount of data in bytes, optionally using the BASS_STREAMPROC_END flag to signify the end of the stream. 0 can be used to just check how much data is queued. + If successful, the amount of queued data is returned, else -1 is returned. Use to get the error code. + + As much data as possible will be placed in the stream's playback buffer, and any remainder will be queued for when more space becomes available, ie. as the buffered data is played. + With a decoding channel, there is no playback buffer, so all data is queued in that case. There is no limit to the amount of data that can be queued, besides available memory. + The queue buffer will be automatically enlarged as required to hold the data, but it can also be enlarged in advance. The queue buffer is freed when the stream ends or is reset, eg. via (with restart = TRUE) or (with pos = 0). + DSP/FX are applied when the data reaches the playback buffer, or the call in the case of a decoding channel. + Data should be provided at a rate sufficent to sustain playback. If the buffer gets exhausted, BASS will automatically stall playback of the stream, until more data is provided. + (BASS_DATA_AVAILABLE) can be used to check the buffer level, and can be used to check if playback has stalled. + A BASS_SYNC_STALL sync can also be set via , to be triggered upon playback stalling or resuming. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe stream is not using the push system. + BASS_ERROR_ILLPARAM is not valid, it must equate to a whole number of samples. + BASS_ERROR_ENDEDThe stream has ended. + BASS_ERROR_MEMThere is insufficient memory. + + + + + Creating a stream duplicate: + + private DSPPROC _dupCallback; + ... + // create stream on device 1 + Bass.BASS_SetDevice(1); + int orig = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_SAMPLE_LOOP); + Bass.BASS_ChannelPlay(orig, false); + ... + // create a clone on device 2 + BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(stream); + Bass.BASS_SetDevice(2); + int clone = Bass.BASS_StreamCreatePush(info.freq, info.chans, info.flags, IntPtr.Zero); + // pause source stream to synchonise buffer contents + Bass.BASS_ChannelPause(stream); + int c = Bass.BASS_ChannelGetData(stream, IntPtr.Zero, (int)BASSData.BASS_DATA_AVAILABLE); + byte[] buf = new byte[c]; + Bass.BASS_ChannelGetData(stream, buf, c); + Bass.BASS_StreamPutData(clone, buf, c); + // set DSP to copy new data from source stream + _dupCallback = new DSPPROC(DupDSP); + Bass.BASS_ChannelSetDSP(orig, _dupCallback, new IntPtr(clone), 0); + Bass.BASS_ChannelPlay(orig, false); // resume source + Bass.BASS_ChannelPlay(clone, false); // play clone + ... + private void DupDSP(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + Bass.BASS_StreamPutData(user.ToInt32(), buffer, length); + } + + + Private _dupCallback As DSPPROC + ... + ' create stream on device 1 + Bass.BASS_SetDevice(1) + Dim orig As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_SAMPLE_LOOP) + Bass.BASS_ChannelPlay(orig, False) + ... + ' create a clone on device 2 + Dim info As BASS_CHANNELINFO = Bass.BASS_ChannelGetInfo(stream) + Bass.BASS_SetDevice(2) + Dim clone As Integer = Bass.BASS_StreamCreatePush(info.freq, info.chans, info.flags, IntPtr.Zero) + ' pause source stream to synchonise buffer contents + Bass.BASS_ChannelPause(stream) + Dim c As Integer = Bass.BASS_ChannelGetData(stream, IntPtr.Zero, CInt(BASSData.BASS_DATA_AVAILABLE)) + Dim buf(c) As Byte + Bass.BASS_ChannelGetData(stream, buf, c) + Bass.BASS_StreamPutData(clone, buf, c) + ' set DSP to copy new data from source stream + _dupCallback = New DSPPROC(DupDSP) + Bass.BASS_ChannelSetDSP(orig, _dupCallback, New IntPtr(clone), 0) + Bass.BASS_ChannelPlay(orig, False) ' resume source + Bass.BASS_ChannelPlay(clone, False) ' play clone + ... + Private Sub DupDSP(handle As Integer, channel As Integer, + buffer As IntPtr, length As Integer, user As IntPtr) + Bass.BASS_StreamPutData(user.ToInt32(), buffer, length) + End Sub + + + + + + Adds sample data to a "push" stream. + + The stream handle (as created with ). + The array of float sample data to provide ( = allocate space in the queue buffer so that there is at least length bytes of free space). + The amount of data in bytes! (buffer.Length/4), optionally using the BASS_STREAMPROC_END flag to signify the end of the stream. 0 can be used to just check how much data is queued. + If successful, the amount of queued data is returned, else -1 is returned. Use to get the error code. + + As much data as possible will be placed in the stream's playback buffer, and any remainder will be queued for when more space becomes available, ie. as the buffered data is played. + With a decoding channel, there is no playback buffer, so all data is queued in that case. There is no limit to the amount of data that can be queued, besides available memory. + The queue buffer will be automatically enlarged as required to hold the data, but it can also be enlarged in advance. The queue buffer is freed when the stream ends or is reset, eg. via (with restart = TRUE) or (with pos = 0). + DSP/FX are applied when the data reaches the playback buffer, or the call in the case of a decoding channel. + Data should be provided at a rate sufficent to sustain playback. If the buffer gets exhausted, BASS will automatically stall playback of the stream, until more data is provided. + (BASS_DATA_AVAILABLE) can be used to check the buffer level, and can be used to check if playback has stalled. + A BASS_SYNC_STALL sync can also be set via , to be triggered upon playback stalling or resuming. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe stream is not using the push system. + BASS_ERROR_ILLPARAM is not valid, it must equate to a whole number of samples. + BASS_ERROR_ENDEDThe stream has ended. + BASS_ERROR_MEMThere is insufficient memory. + + + + + Creating a stream duplicate: + + private DSPPROC _dupCallback; + ... + // create stream on device 1 + Bass.BASS_SetDevice(1); + int orig = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_SAMPLE_LOOP); + Bass.BASS_ChannelPlay(orig, false); + ... + // create a clone on device 2 + BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(stream); + Bass.BASS_SetDevice(2); + int clone = Bass.BASS_StreamCreatePush(info.freq, info.chans, info.flags, IntPtr.Zero); + // pause source stream to synchonise buffer contents + Bass.BASS_ChannelPause(stream); + int c = Bass.BASS_ChannelGetData(stream, IntPtr.Zero, (int)BASSData.BASS_DATA_AVAILABLE); + byte[] buf = new byte[c]; + Bass.BASS_ChannelGetData(stream, buf, c); + Bass.BASS_StreamPutData(clone, buf, c); + // set DSP to copy new data from source stream + _dupCallback = new DSPPROC(DupDSP); + Bass.BASS_ChannelSetDSP(orig, _dupCallback, new IntPtr(clone), 0); + Bass.BASS_ChannelPlay(orig, false); // resume source + Bass.BASS_ChannelPlay(clone, false); // play clone + ... + private void DupDSP(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + Bass.BASS_StreamPutData(user.ToInt32(), buffer, length); + } + + + Private _dupCallback As DSPPROC + ... + ' create stream on device 1 + Bass.BASS_SetDevice(1) + Dim orig As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_SAMPLE_LOOP) + Bass.BASS_ChannelPlay(orig, False) + ... + ' create a clone on device 2 + Dim info As BASS_CHANNELINFO = Bass.BASS_ChannelGetInfo(stream) + Bass.BASS_SetDevice(2) + Dim clone As Integer = Bass.BASS_StreamCreatePush(info.freq, info.chans, info.flags, IntPtr.Zero) + ' pause source stream to synchonise buffer contents + Bass.BASS_ChannelPause(stream) + Dim c As Integer = Bass.BASS_ChannelGetData(stream, IntPtr.Zero, CInt(BASSData.BASS_DATA_AVAILABLE)) + Dim buf(c) As Byte + Bass.BASS_ChannelGetData(stream, buf, c) + Bass.BASS_StreamPutData(clone, buf, c) + ' set DSP to copy new data from source stream + _dupCallback = New DSPPROC(DupDSP) + Bass.BASS_ChannelSetDSP(orig, _dupCallback, New IntPtr(clone), 0) + Bass.BASS_ChannelPlay(orig, False) ' resume source + Bass.BASS_ChannelPlay(clone, False) ' play clone + ... + Private Sub DupDSP(handle As Integer, channel As Integer, + buffer As IntPtr, length As Integer, user As IntPtr) + Bass.BASS_StreamPutData(user.ToInt32(), buffer, length) + End Sub + + + + + + Adds sample data to a "push" stream. + + The stream handle (as created with ). + The array of Int32 sample data to provide ( = allocate space in the queue buffer so that there is at least length bytes of free space; Caution: Int32=2xInt16, so this overload can e.g. be used to provide a stereo sample containing of two 16-bit values). + The amount of data in bytes! (buffer.Length/4), optionally using the BASS_STREAMPROC_END flag to signify the end of the stream. 0 can be used to just check how much data is queued. + If successful, the amount of queued data is returned, else -1 is returned. Use to get the error code. + + As much data as possible will be placed in the stream's playback buffer, and any remainder will be queued for when more space becomes available, ie. as the buffered data is played. + With a decoding channel, there is no playback buffer, so all data is queued in that case. There is no limit to the amount of data that can be queued, besides available memory. + The queue buffer will be automatically enlarged as required to hold the data, but it can also be enlarged in advance. The queue buffer is freed when the stream ends or is reset, eg. via (with restart = TRUE) or (with pos = 0). + DSP/FX are applied when the data reaches the playback buffer, or the call in the case of a decoding channel. + Data should be provided at a rate sufficent to sustain playback. If the buffer gets exhausted, BASS will automatically stall playback of the stream, until more data is provided. + (BASS_DATA_AVAILABLE) can be used to check the buffer level, and can be used to check if playback has stalled. + A BASS_SYNC_STALL sync can also be set via , to be triggered upon playback stalling or resuming. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe stream is not using the push system. + BASS_ERROR_ILLPARAM is not valid, it must equate to a whole number of samples. + BASS_ERROR_ENDEDThe stream has ended. + BASS_ERROR_MEMThere is insufficient memory. + + + + + Creating a stream duplicate: + + private DSPPROC _dupCallback; + ... + // create stream on device 1 + Bass.BASS_SetDevice(1); + int orig = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_SAMPLE_LOOP); + Bass.BASS_ChannelPlay(orig, false); + ... + // create a clone on device 2 + BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(stream); + Bass.BASS_SetDevice(2); + int clone = Bass.BASS_StreamCreatePush(info.freq, info.chans, info.flags, IntPtr.Zero); + // pause source stream to synchonise buffer contents + Bass.BASS_ChannelPause(stream); + int c = Bass.BASS_ChannelGetData(stream, IntPtr.Zero, (int)BASSData.BASS_DATA_AVAILABLE); + byte[] buf = new byte[c]; + Bass.BASS_ChannelGetData(stream, buf, c); + Bass.BASS_StreamPutData(clone, buf, c); + // set DSP to copy new data from source stream + _dupCallback = new DSPPROC(DupDSP); + Bass.BASS_ChannelSetDSP(orig, _dupCallback, new IntPtr(clone), 0); + Bass.BASS_ChannelPlay(orig, false); // resume source + Bass.BASS_ChannelPlay(clone, false); // play clone + ... + private void DupDSP(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + Bass.BASS_StreamPutData(user.ToInt32(), buffer, length); + } + + + Private _dupCallback As DSPPROC + ... + ' create stream on device 1 + Bass.BASS_SetDevice(1) + Dim orig As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_SAMPLE_LOOP) + Bass.BASS_ChannelPlay(orig, False) + ... + ' create a clone on device 2 + Dim info As BASS_CHANNELINFO = Bass.BASS_ChannelGetInfo(stream) + Bass.BASS_SetDevice(2) + Dim clone As Integer = Bass.BASS_StreamCreatePush(info.freq, info.chans, info.flags, IntPtr.Zero) + ' pause source stream to synchonise buffer contents + Bass.BASS_ChannelPause(stream) + Dim c As Integer = Bass.BASS_ChannelGetData(stream, IntPtr.Zero, CInt(BASSData.BASS_DATA_AVAILABLE)) + Dim buf(c) As Byte + Bass.BASS_ChannelGetData(stream, buf, c) + Bass.BASS_StreamPutData(clone, buf, c) + ' set DSP to copy new data from source stream + _dupCallback = New DSPPROC(DupDSP) + Bass.BASS_ChannelSetDSP(orig, _dupCallback, New IntPtr(clone), 0) + Bass.BASS_ChannelPlay(orig, False) ' resume source + Bass.BASS_ChannelPlay(clone, False) ' play clone + ... + Private Sub DupDSP(handle As Integer, channel As Integer, + buffer As IntPtr, length As Integer, user As IntPtr) + Bass.BASS_StreamPutData(user.ToInt32(), buffer, length) + End Sub + + + + + + Adds sample data to a "push" stream. + + The stream handle (as created with ). + The array of Int16 sample data to provide ( = allocate space in the queue buffer so that there is at least length bytes of free space). + The amount of data in bytes! (buffer.Length/2), optionally using the BASS_STREAMPROC_END flag to signify the end of the stream. 0 can be used to just check how much data is queued. + If successful, the amount of queued data is returned, else -1 is returned. Use to get the error code. + + As much data as possible will be placed in the stream's playback buffer, and any remainder will be queued for when more space becomes available, ie. as the buffered data is played. + With a decoding channel, there is no playback buffer, so all data is queued in that case. There is no limit to the amount of data that can be queued, besides available memory. + The queue buffer will be automatically enlarged as required to hold the data, but it can also be enlarged in advance. The queue buffer is freed when the stream ends or is reset, eg. via (with restart = TRUE) or (with pos = 0). + DSP/FX are applied when the data reaches the playback buffer, or the call in the case of a decoding channel. + Data should be provided at a rate sufficent to sustain playback. If the buffer gets exhausted, BASS will automatically stall playback of the stream, until more data is provided. + (BASS_DATA_AVAILABLE) can be used to check the buffer level, and can be used to check if playback has stalled. + A BASS_SYNC_STALL sync can also be set via , to be triggered upon playback stalling or resuming. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe stream is not using the push system. + BASS_ERROR_ILLPARAM is not valid, it must equate to a whole number of samples. + BASS_ERROR_ENDEDThe stream has ended. + BASS_ERROR_MEMThere is insufficient memory. + + + + + Creating a stream duplicate: + + private DSPPROC _dupCallback; + ... + // create stream on device 1 + Bass.BASS_SetDevice(1); + int orig = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_SAMPLE_LOOP); + Bass.BASS_ChannelPlay(orig, false); + ... + // create a clone on device 2 + BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(stream); + Bass.BASS_SetDevice(2); + int clone = Bass.BASS_StreamCreatePush(info.freq, info.chans, info.flags, IntPtr.Zero); + // pause source stream to synchonise buffer contents + Bass.BASS_ChannelPause(stream); + int c = Bass.BASS_ChannelGetData(stream, IntPtr.Zero, (int)BASSData.BASS_DATA_AVAILABLE); + byte[] buf = new byte[c]; + Bass.BASS_ChannelGetData(stream, buf, c); + Bass.BASS_StreamPutData(clone, buf, c); + // set DSP to copy new data from source stream + _dupCallback = new DSPPROC(DupDSP); + Bass.BASS_ChannelSetDSP(orig, _dupCallback, new IntPtr(clone), 0); + Bass.BASS_ChannelPlay(orig, false); // resume source + Bass.BASS_ChannelPlay(clone, false); // play clone + ... + private void DupDSP(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + Bass.BASS_StreamPutData(user.ToInt32(), buffer, length); + } + + + Private _dupCallback As DSPPROC + ... + ' create stream on device 1 + Bass.BASS_SetDevice(1) + Dim orig As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_SAMPLE_LOOP) + Bass.BASS_ChannelPlay(orig, False) + ... + ' create a clone on device 2 + Dim info As BASS_CHANNELINFO = Bass.BASS_ChannelGetInfo(stream) + Bass.BASS_SetDevice(2) + Dim clone As Integer = Bass.BASS_StreamCreatePush(info.freq, info.chans, info.flags, IntPtr.Zero) + ' pause source stream to synchonise buffer contents + Bass.BASS_ChannelPause(stream) + Dim c As Integer = Bass.BASS_ChannelGetData(stream, IntPtr.Zero, CInt(BASSData.BASS_DATA_AVAILABLE)) + Dim buf(c) As Byte + Bass.BASS_ChannelGetData(stream, buf, c) + Bass.BASS_StreamPutData(clone, buf, c) + ' set DSP to copy new data from source stream + _dupCallback = New DSPPROC(DupDSP) + Bass.BASS_ChannelSetDSP(orig, _dupCallback, New IntPtr(clone), 0) + Bass.BASS_ChannelPlay(orig, False) ' resume source + Bass.BASS_ChannelPlay(clone, False) ' play clone + ... + Private Sub DupDSP(handle As Integer, channel As Integer, + buffer As IntPtr, length As Integer, user As IntPtr) + Bass.BASS_StreamPutData(user.ToInt32(), buffer, length) + End Sub + + + + + + Adds sample data to a "push" stream. + + The stream handle (as created with ). + The array of byte sample data to provide ( = allocate space in the queue buffer so that there is at least length bytes of free space). + The amount of data in bytes, optionally using the BASS_STREAMPROC_END flag to signify the end of the stream. 0 can be used to just check how much data is queued. + If successful, the amount of queued data is returned, else -1 is returned. Use to get the error code. + + As much data as possible will be placed in the stream's playback buffer, and any remainder will be queued for when more space becomes available, ie. as the buffered data is played. + With a decoding channel, there is no playback buffer, so all data is queued in that case. There is no limit to the amount of data that can be queued, besides available memory. + The queue buffer will be automatically enlarged as required to hold the data, but it can also be enlarged in advance. The queue buffer is freed when the stream ends or is reset, eg. via (with restart = TRUE) or (with pos = 0). + DSP/FX are applied when the data reaches the playback buffer, or the call in the case of a decoding channel. + Data should be provided at a rate sufficent to sustain playback. If the buffer gets exhausted, BASS will automatically stall playback of the stream, until more data is provided. + (BASS_DATA_AVAILABLE) can be used to check the buffer level, and can be used to check if playback has stalled. + A BASS_SYNC_STALL sync can also be set via , to be triggered upon playback stalling or resuming. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe stream is not using the push system. + BASS_ERROR_ILLPARAM is not valid, it must equate to a whole number of samples. + BASS_ERROR_ENDEDThe stream has ended. + BASS_ERROR_MEMThere is insufficient memory. + + + + + Creating a stream duplicate: + + private DSPPROC _dupCallback; + ... + // create stream on device 1 + Bass.BASS_SetDevice(1); + int orig = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_SAMPLE_LOOP); + Bass.BASS_ChannelPlay(orig, false); + ... + // create a clone on device 2 + BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(stream); + Bass.BASS_SetDevice(2); + int clone = Bass.BASS_StreamCreatePush(info.freq, info.chans, info.flags, IntPtr.Zero); + // pause source stream to synchonise buffer contents + Bass.BASS_ChannelPause(stream); + int c = Bass.BASS_ChannelGetData(stream, IntPtr.Zero, (int)BASSData.BASS_DATA_AVAILABLE); + byte[] buf = new byte[c]; + Bass.BASS_ChannelGetData(stream, buf, c); + Bass.BASS_StreamPutData(clone, buf, c); + // set DSP to copy new data from source stream + _dupCallback = new DSPPROC(DupDSP); + Bass.BASS_ChannelSetDSP(orig, _dupCallback, new IntPtr(clone), 0); + Bass.BASS_ChannelPlay(orig, false); // resume source + Bass.BASS_ChannelPlay(clone, false); // play clone + ... + private void DupDSP(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + Bass.BASS_StreamPutData(user.ToInt32(), buffer, length); + } + + + Private _dupCallback As DSPPROC + ... + ' create stream on device 1 + Bass.BASS_SetDevice(1) + Dim orig As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_SAMPLE_LOOP) + Bass.BASS_ChannelPlay(orig, False) + ... + ' create a clone on device 2 + Dim info As BASS_CHANNELINFO = Bass.BASS_ChannelGetInfo(stream) + Bass.BASS_SetDevice(2) + Dim clone As Integer = Bass.BASS_StreamCreatePush(info.freq, info.chans, info.flags, IntPtr.Zero) + ' pause source stream to synchonise buffer contents + Bass.BASS_ChannelPause(stream) + Dim c As Integer = Bass.BASS_ChannelGetData(stream, IntPtr.Zero, CInt(BASSData.BASS_DATA_AVAILABLE)) + Dim buf(c) As Byte + Bass.BASS_ChannelGetData(stream, buf, c) + Bass.BASS_StreamPutData(clone, buf, c) + ' set DSP to copy new data from source stream + _dupCallback = New DSPPROC(DupDSP) + Bass.BASS_ChannelSetDSP(orig, _dupCallback, New IntPtr(clone), 0) + Bass.BASS_ChannelPlay(orig, False) ' resume source + Bass.BASS_ChannelPlay(clone, False) ' play clone + ... + Private Sub DupDSP(handle As Integer, channel As Integer, + buffer As IntPtr, length As Integer, user As IntPtr) + Bass.BASS_StreamPutData(user.ToInt32(), buffer, length) + End Sub + + + + + + Adds sample data to a "push" stream. + + The stream handle (as created with ). + The array of byte sample data to provide. + The start index within the to provide the data from. + The amount of data in bytes (starting at ), optionally using the BASS_STREAMPROC_END flag to signify the end of the stream. 0 can be used to just check how much data is queued. + If successful, the amount of queued data is returned, else -1 is returned. Use to get the error code. + + As much data as possible will be placed in the stream's playback buffer, and any remainder will be queued for when more space becomes available, ie. as the buffered data is played. + With a decoding channel, there is no playback buffer, so all data is queued in that case. There is no limit to the amount of data that can be queued, besides available memory. + The queue buffer will be automatically enlarged as required to hold the data, but it can also be enlarged in advance. The queue buffer is freed when the stream ends or is reset, eg. via (with restart = TRUE) or (with pos = 0). + DSP/FX are applied when the data reaches the playback buffer, or the call in the case of a decoding channel. + Data should be provided at a rate sufficent to sustain playback. If the buffer gets exhausted, BASS will automatically stall playback of the stream, until more data is provided. + (BASS_DATA_AVAILABLE) can be used to check the buffer level, and can be used to check if playback has stalled. + A BASS_SYNC_STALL sync can also be set via , to be triggered upon playback stalling or resuming. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe stream is not using the push system. + BASS_ERROR_ILLPARAM is not valid, it must equate to a whole number of samples. + BASS_ERROR_ENDEDThe stream has ended. + BASS_ERROR_MEMThere is insufficient memory. + + + + + + + Adds data to a "push buffered" user file stream's buffer. + + The stream handle (as created with and the STREAMFILE_BUFFERPUSH system flag.). + Pointer to the file data. + The amount of data in bytes, or BASS_STREAMPROC_END to end the file. + If successful, the number of bytes read from buffer is returned, else -1 is returned. Use to get the error code. + + If there is not enough space in the stream's file buffer to receive all of the data, then only the amount that will fit is read from buffer. can be used to check the amount of space in the buffer. + File data should be provided at a rate sufficent to sustain playback. If there is insufficient file data, and the playback buffer is subsequently exhausted, BASS will automatically stall playback of the stream, until more data is available. A BASS_SYNC_STALL sync can be set via , to be triggered upon playback stalling or resuming. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe stream is not using the STREAMFILE_BUFFERPUSH file system. + BASS_ERROR_ENDEDThe stream has ended. + + + + + + + Adds data to a "push buffered" user file stream's buffer. + + The stream handle (as created with and the STREAMFILE_BUFFERPUSH system flag.). + The array of float values to provide to the file data. + The amount of data in bytes! (buffer.Length/4), or BASS_STREAMPROC_END to end the file. + If successful, the number of bytes read from buffer is returned, else -1 is returned. Use to get the error code. + + If there is not enough space in the stream's file buffer to receive all of the data, then only the amount that will fit is read from buffer. can be used to check the amount of space in the buffer. + File data should be provided at a rate sufficent to sustain playback. If there is insufficient file data, and the playback buffer is subsequently exhausted, BASS will automatically stall playback of the stream, until more data is available. A BASS_SYNC_STALL sync can be set via , to be triggered upon playback stalling or resuming. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe stream is not using the STREAMFILE_BUFFERPUSH file system. + BASS_ERROR_ENDEDThe stream has ended. + + + + + + + Adds data to a "push buffered" user file stream's buffer. + + The stream handle (as created with and the STREAMFILE_BUFFERPUSH system flag.). + The array of Int32 values to provide to the file data (Caution: Int32=2xInt16, so this overload can e.g. be used to provide a stereo sample containing of two 16-bit values). + The amount of data in bytes! (buffer.Length/4), or BASS_STREAMPROC_END to end the file. + If successful, the number of bytes read from buffer is returned, else -1 is returned. Use to get the error code. + + If there is not enough space in the stream's file buffer to receive all of the data, then only the amount that will fit is read from buffer. can be used to check the amount of space in the buffer. + File data should be provided at a rate sufficent to sustain playback. If there is insufficient file data, and the playback buffer is subsequently exhausted, BASS will automatically stall playback of the stream, until more data is available. A BASS_SYNC_STALL sync can be set via , to be triggered upon playback stalling or resuming. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe stream is not using the STREAMFILE_BUFFERPUSH file system. + BASS_ERROR_ENDEDThe stream has ended. + + + + + + + Adds data to a "push buffered" user file stream's buffer. + + The stream handle (as created with and the STREAMFILE_BUFFERPUSH system flag.). + The array of Int16 values to provide to the file data. + The amount of data in bytes! (buffer.Length/2), or BASS_STREAMPROC_END to end the file. + If successful, the number of bytes read from buffer is returned, else -1 is returned. Use to get the error code. + + If there is not enough space in the stream's file buffer to receive all of the data, then only the amount that will fit is read from buffer. can be used to check the amount of space in the buffer. + File data should be provided at a rate sufficent to sustain playback. If there is insufficient file data, and the playback buffer is subsequently exhausted, BASS will automatically stall playback of the stream, until more data is available. A BASS_SYNC_STALL sync can be set via , to be triggered upon playback stalling or resuming. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe stream is not using the STREAMFILE_BUFFERPUSH file system. + BASS_ERROR_ENDEDThe stream has ended. + + + + + + + Adds data to a "push buffered" user file stream's buffer. + + The stream handle (as created with and the STREAMFILE_BUFFERPUSH system flag.). + The array of byte values to provide to the file data. + The amount of data in bytes, or BASS_STREAMPROC_END to end the file. + If successful, the number of bytes read from buffer is returned, else -1 is returned. Use to get the error code. + + If there is not enough space in the stream's file buffer to receive all of the data, then only the amount that will fit is read from buffer. can be used to check the amount of space in the buffer. + File data should be provided at a rate sufficent to sustain playback. If there is insufficient file data, and the playback buffer is subsequently exhausted, BASS will automatically stall playback of the stream, until more data is available. A BASS_SYNC_STALL sync can be set via , to be triggered upon playback stalling or resuming. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe stream is not using the STREAMFILE_BUFFERPUSH file system. + BASS_ERROR_ENDEDThe stream has ended. + + + + + + + Only used internally! See the file overload of for details! + + Needs to be set to + The filename to load. + File offset to load the MOD music from. + Data length... 0 = use all data up to the end of file. + A combination of these flags (see ). + Sample rate to render/play the MOD music at... 0 = the rate specified in the call. + If successful, the loaded music's handle is returned, else 0 is returned. Use to get the error code. + + + + Loads a MOD music file - MO3 / IT / XM / S3M / MTM / MOD / UMX formats. + This overload implements Unicode filenames. The BASS_UNICODE flag will be added automatically. + + The file name from where to load the music. + File offset to load the MOD music from. + Data length... 0 = use all data up to the end of file. If length over-runs the end of the file, it'll automatically be lowered to the end of the file. + A combination of these flags (see ): + + BASS_SAMPLE_8BITSUse 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the sample data will be 16-bit. + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_MUSIC_DECODE flag are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_MONODecode/play the MOD music in mono (uses less CPU than stereo). This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + BASS_SAMPLE_SOFTWAREForce the MOD music to not use hardware mixing. + BASS_SAMPLE_3DEnable 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D channels are mono, so BASS_SAMPLE_MONO is automatically applied. The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the music. + BASS_SAMPLE_LOOPLoop the music. + BASS_MUSIC_RAMPUse "normal" ramping (as used in FastTracker 2). + BASS_MUSIC_RAMPSUse "sensitive" ramping". + BASS_MUSIC_NONINTERUse non-interpolated mixing. This generally reduces the sound quality, but can be good for chip-tunes. + BASS_MUSIC_SINCINTERUse sinc interpolated sample mixing. This increases the sound quality, but also requires quite a bit more processing. If neither this or the BASS_MUSIC_NONINTER flag is specified, linear interpolation is used. + BASS_MUSIC_FT2MODPlay .MOD file as FastTracker 2 would. + BASS_MUSIC_PT1MODPlay .MOD file as ProTracker 1 would. + BASS_MUSIC_POSRESETStop all notes when seeking (using ). + BASS_MUSIC_POSRESETEXStop all notes and reset bpm/etc when seeking. + BASS_MUSIC_SURROUNDApply XMPlay's surround sound to the music (ignored in mono). + BASS_MUSIC_SURROUND2Apply XMPlay's surround sound mode 2 to the music (ignored in mono). + BASS_MUSIC_STOPBACKStop the music when a backward jump effect is played. This stops musics that never reach the end from going into endless loops. Some MOD musics are designed to jump all over the place, so this flag would cause those to be stopped prematurely. If this flag is used together with the BASS_SAMPLE_LOOP flag, then the music would not be stopped but any BASS_SYNC_END sync would be triggered. + BASS_MUSIC_PRESCANCalculate the playback length of the music, and enable seeking in bytes. This slightly increases the time taken to load the music, depending on how long it is. In the case of musics that loop, the length until the loop occurs is calculated. Use BASS_ChannelGetLength to retrieve the length. + BASS_MUSIC_NOSAMPLEDon't load the samples. This reduces the time taken to load the music, notably with MO3 files, which is useful if you just want to get the name and length of the music without playing it. + BASS_MUSIC_AUTOFREEAutomatically free the music when it ends. This allows you to play a music and forget about it, as BASS will automatically free the music's resources when it has reached the end or when (or ) is called. Note that some musics never actually end on their own (ie. without you stopping them). + BASS_MUSIC_DECODEDecode the music into sample data, without outputting it. Use to retrieve decoded sample data. BASS_SAMPLE_SOFTWARE/3D/FX/AUTOFREE are ignored when using this flag, as are the SPEAKER flags. + BASS_SPEAKER_xxxSpeaker assignment flags. The BASS_SAMPLE_MONO flag is automatically applied when using a mono speaker assignment flag. + BASS_UNICODEfile is a Unicode (16-bit characters) filename (not needed with this overload). + + + Sample rate to render/play the MOD music at... 0 = the rate specified in the call. + If successful, the loaded music's handle is returned, else 0 is returned. Use to get the error code. + + BASS uses the same code as XMPlay for it's MOD music support, giving the most accurate reproduction of MO3 / IT / XM / S3M / MTM / MOD / UMX files available from any sound system. + MO3s are treated and used in exactly the same way as normal MOD musics. The advantage of MO3s is that they can be a lot smaller with virtually identical quality. Playing a MO3 does not use any more CPU power than playing the original MOD version does. The only difference is a slightly longer load time as the samples are being decoded. MO3 files are created using the MO3 encoder available at the BASS website. + DMO effects (the same as available with ) can be used in IT and XM files (and MO3 versions of them) created with Modplug Tracker. This allows effects to be added to a track without having to resort to an MP3 or OGG version, so it can remain small and still sound fancy. Of course, the effects require some CPU, so should not be used carelessly if performance is key. DirectX 8 (or above) is required for the effects to be heard - without that, the music can still be played, but the effects are disabled. + "Ramping" does not take a lot of extra processing and improves the sound quality by removing clicks, by ramping/smoothing volume and pan changes. The start of a sample may also be ramped-in. That is always the case with XM files (or MOD files in FT2 mode) when using normal ramping, and possibly with all formats when using sensitive ramping; senstitive ramping will only ramp-in when necessary to avoid a click. Generally, normal ramping is recommended for XM files, and sensitive ramping for the other formats, but some XM files may also sound better using sensitive ramping. + When loading a MOD music from memory, BASS does not use the memory after it's loaded the MOD music. So you can do whatever you want with the memory after calling this function. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILThe BASS_MUSIC_AUTOFREE flag is unavailable to decoding channels. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + Away from Windows, all mixing is done in software (by BASS), so the BASS_SAMPLE_SOFTWARE flag is unnecessary. The BASS_SAMPLE_FX flag is also ignored. + DMO effects are not supported in MOD music on Windows CE, and DirectX 8 (or above) is required on Windows. They are always available on other platforms, except for the following: Compressor, Gargle, and I3DL2Reverb. When a DMO effect is unavailable, the MOD music can still be played, but the effect will be disabled. + + + + int music = Bass.BASS_MusicLoad("test.mod", 0, 0, BASSFlag.BASS_DEFAULT, 0); + + + Dim music As Integer = Bass.BASS_MusicLoad("test.mod", 0, 0, BASSFlag.BASS_DEFAULT, 0) + + + + + + Only used internally! See the file overload of for details! + + Needs to be set to + An IntPtr to the memory block. + File offset to load the MOD music from. + Needs to be set to the length of the buffer data which should be played. + A combination of these flags (see ). + Sample rate to render/play the MOD music at... 0 = the rate specified in the call. + If successful, the loaded music's handle is returned, else 0 is returned. Use to get the error code. + + + + Loads a MOD music file - MO3 / IT / XM / S3M / MTM / MOD / UMX formats. + This overload implements loading from memory. + + An unmanaged pointer to the memory location as an IntPtr. + File offset to load the MOD music from. + Data length... 0 = use all data up to the end of file. If length over-runs the end of the file, it'll automatically be lowered to the end of the file. + A combination of these flags (see ): + + BASS_SAMPLE_8BITSUse 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the sample data will be 16-bit. + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_MUSIC_DECODE flag are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_MONODecode/play the MOD music in mono (uses less CPU than stereo). This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + BASS_SAMPLE_SOFTWAREForce the MOD music to not use hardware mixing. + BASS_SAMPLE_3DEnable 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D channels are mono, so BASS_SAMPLE_MONO is automatically applied. The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the music. + BASS_SAMPLE_LOOPLoop the music. + BASS_MUSIC_RAMPUse "normal" ramping (as used in FastTracker 2). + BASS_MUSIC_RAMPSUse "sensitive" ramping". + BASS_MUSIC_NONINTERUse non-interpolated mixing. This generally reduces the sound quality, but can be good for chip-tunes. + BASS_MUSIC_SINCINTERUse sinc interpolated sample mixing. This increases the sound quality, but also requires quite a bit more processing. If neither this or the BASS_MUSIC_NONINTER flag is specified, linear interpolation is used. + BASS_MUSIC_FT2MODPlay .MOD file as FastTracker 2 would. + BASS_MUSIC_PT1MODPlay .MOD file as ProTracker 1 would. + BASS_MUSIC_POSRESETStop all notes when seeking (using ). + BASS_MUSIC_POSRESETEXStop all notes and reset bpm/etc when seeking. + BASS_MUSIC_SURROUNDApply XMPlay's surround sound to the music (ignored in mono). + BASS_MUSIC_SURROUND2Apply XMPlay's surround sound mode 2 to the music (ignored in mono). + BASS_MUSIC_STOPBACKStop the music when a backward jump effect is played. This stops musics that never reach the end from going into endless loops. Some MOD musics are designed to jump all over the place, so this flag would cause those to be stopped prematurely. If this flag is used together with the BASS_SAMPLE_LOOP flag, then the music would not be stopped but any BASS_SYNC_END sync would be triggered. + BASS_MUSIC_PRESCANCalculate the playback length of the music, and enable seeking in bytes. This slightly increases the time taken to load the music, depending on how long it is. In the case of musics that loop, the length until the loop occurs is calculated. Use BASS_ChannelGetLength to retrieve the length. + BASS_MUSIC_NOSAMPLEDon't load the samples. This reduces the time taken to load the music, notably with MO3 files, which is useful if you just want to get the name and length of the music without playing it. + BASS_MUSIC_AUTOFREEAutomatically free the music when it ends. This allows you to play a music and forget about it, as BASS will automatically free the music's resources when it has reached the end or when (or ) is called. Note that some musics never actually end on their own (ie. without you stopping them). + BASS_MUSIC_DECODEDecode the music into sample data, without outputting it. Use to retrieve decoded sample data. BASS_SAMPLE_SOFTWARE/3D/FX/AUTOFREE are ignored when using this flag, as are the SPEAKER flags. + BASS_SPEAKER_xxxSpeaker assignment flags. The BASS_SAMPLE_MONO flag is automatically applied when using a mono speaker assignment flag. + + + Sample rate to render/play the MOD music at... 0 = the rate specified in the call. + If successful, the loaded music's handle is returned, else 0 is returned. Use to get the error code. + + BASS uses the same code as XMPlay for it's MOD music support, giving the most accurate reproduction of MO3 / IT / XM / S3M / MTM / MOD / UMX files available from any sound system. + MO3s are treated and used in exactly the same way as normal MOD musics. The advantage of MO3s is that they can be a lot smaller with virtually identical quality. Playing a MO3 does not use any more CPU power than playing the original MOD version does. The only difference is a slightly longer load time as the samples are being decoded. MO3 files are created using the MO3 encoder available at the BASS website. + DMO effects (the same as available with ) can be used in IT and XM files (and MO3 versions of them) created with Modplug Tracker. This allows effects to be added to a track without having to resort to an MP3 or OGG version, so it can remain small and still sound fancy. Of course, the effects require some CPU, so should not be used carelessly if performance is key. DirectX 8 (or above) is required for the effects to be heard - without that, the music can still be played, but the effects are disabled. + Ramping doesn't take a lot of extra processing and improves the sound quality by removing "clicks". Sensitive ramping leaves sharp attacked samples, while normal ramping can cause them to lose a-bit of their impact. Generally, normal ramping is recommended for XMs, and sensitive ramping for the other formats. But, some XMs may also sound better using sensitive ramping. + When loading a MOD music from memory, BASS does not use the memory after it's loaded the MOD music. So you can do whatever you want with the memory after calling this function. + This means there is no need to pin the memory buffer for this method. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILThe BASS_MUSIC_AUTOFREE flag is unavailable to decoding channels. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + Away from Windows, all mixing is done in software (by BASS), so the BASS_SAMPLE_SOFTWARE flag is unnecessary. The BASS_SAMPLE_FX flag is also ignored. + DMO effects are not supported in MOD music on Windows CE, and DirectX 8 (or above) is required on Windows. They are always available on other platforms, except for the following: Compressor, Gargle, and I3DL2Reverb. When a DMO effect is unavailable, the MOD music can still be played, but the effect will be disabled. + + + See for examples on how to load data from memory. + + + + + Only used internally! See the file overload of for details! + + Needs to be set to + An IntPtr to the memory block. + File offset to load the MOD music from. + Needs to be set to the length of the buffer data which should be played. + A combination of these flags (see ). + Sample rate to render/play the MOD music at... 0 = the rate specified in the call. + If successful, the loaded music's handle is returned, else 0 is returned. Use to get the error code. + + + + Loads a MOD music file - MO3 / IT / XM / S3M / MTM / MOD / UMX formats. + This overload implements loading from memory. + + A managed memory location as a byte[]. + File offset to load the MOD music from. + Data length... 0 = use all data up to the end of file. If length over-runs the end of the file, it'll automatically be lowered to the end of the file. + A combination of these flags (see ): + + BASS_SAMPLE_8BITSUse 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the sample data will be 16-bit. + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers or the BASS_MUSIC_DECODE flag are required to use this flag in Windows. See Floating-point channels for more info. + BASS_SAMPLE_MONODecode/play the MOD music in mono (uses less CPU than stereo). This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + BASS_SAMPLE_SOFTWAREForce the MOD music to not use hardware mixing. + BASS_SAMPLE_3DEnable 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . 3D channels are mono, so BASS_SAMPLE_MONO is automatically applied. The SPEAKER flags can not be used together with this flag. + BASS_SAMPLE_FXRequires DirectX 8 or above: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. Use to add effects to the music. + BASS_SAMPLE_LOOPLoop the music. + BASS_MUSIC_RAMPUse "normal" ramping (as used in FastTracker 2). + BASS_MUSIC_RAMPSUse "sensitive" ramping". + BASS_MUSIC_NONINTERUse non-interpolated mixing. This generally reduces the sound quality, but can be good for chip-tunes. + BASS_MUSIC_SINCINTERUse sinc interpolated sample mixing. This increases the sound quality, but also requires quite a bit more processing. If neither this or the BASS_MUSIC_NONINTER flag is specified, linear interpolation is used. + BASS_MUSIC_FT2MODPlay .MOD file as FastTracker 2 would. + BASS_MUSIC_PT1MODPlay .MOD file as ProTracker 1 would. + BASS_MUSIC_POSRESETStop all notes when seeking (using ). + BASS_MUSIC_POSRESETEXStop all notes and reset bpm/etc when seeking. + BASS_MUSIC_SURROUNDApply XMPlay's surround sound to the music (ignored in mono). + BASS_MUSIC_SURROUND2Apply XMPlay's surround sound mode 2 to the music (ignored in mono). + BASS_MUSIC_STOPBACKStop the music when a backward jump effect is played. This stops musics that never reach the end from going into endless loops. Some MOD musics are designed to jump all over the place, so this flag would cause those to be stopped prematurely. If this flag is used together with the BASS_SAMPLE_LOOP flag, then the music would not be stopped but any BASS_SYNC_END sync would be triggered. + BASS_MUSIC_PRESCANCalculate the playback length of the music, and enable seeking in bytes. This slightly increases the time taken to load the music, depending on how long it is. In the case of musics that loop, the length until the loop occurs is calculated. Use BASS_ChannelGetLength to retrieve the length. + BASS_MUSIC_NOSAMPLEDon't load the samples. This reduces the time taken to load the music, notably with MO3 files, which is useful if you just want to get the name and length of the music without playing it. + BASS_MUSIC_AUTOFREEAutomatically free the music when it ends. This allows you to play a music and forget about it, as BASS will automatically free the music's resources when it has reached the end or when (or ) is called. Note that some musics never actually end on their own (ie. without you stopping them). + BASS_MUSIC_DECODEDecode the music into sample data, without outputting it. Use to retrieve decoded sample data. BASS_SAMPLE_SOFTWARE/3D/FX/AUTOFREE are ignored when using this flag, as are the SPEAKER flags. + BASS_SPEAKER_xxxSpeaker assignment flags. The BASS_SAMPLE_MONO flag is automatically applied when using a mono speaker assignment flag. + + + Sample rate to render/play the MOD music at... 0 = the rate specified in the call. + If successful, the loaded music's handle is returned, else 0 is returned. Use to get the error code. + + BASS uses the same code as XMPlay for it's MOD music support, giving the most accurate reproduction of MO3 / IT / XM / S3M / MTM / MOD / UMX files available from any sound system. + MO3s are treated and used in exactly the same way as normal MOD musics. The advantage of MO3s is that they can be a lot smaller with virtually identical quality. Playing a MO3 does not use any more CPU power than playing the original MOD version does. The only difference is a slightly longer load time as the samples are being decoded. MO3 files are created using the MO3 encoder available at the BASS website. + DMO effects (the same as available with ) can be used in IT and XM files (and MO3 versions of them) created with Modplug Tracker. This allows effects to be added to a track without having to resort to an MP3 or OGG version, so it can remain small and still sound fancy. Of course, the effects require some CPU, so should not be used carelessly if performance is key. DirectX 8 (or above) is required for the effects to be heard - without that, the music can still be played, but the effects are disabled. + Ramping doesn't take a lot of extra processing and improves the sound quality by removing "clicks". Sensitive ramping leaves sharp attacked samples, while normal ramping can cause them to lose a-bit of their impact. Generally, normal ramping is recommended for XMs, and sensitive ramping for the other formats. But, some XMs may also sound better using sensitive ramping. + When loading a MOD music from memory, BASS does not use the memory after it's loaded the MOD music. So you can do whatever you want with the memory after calling this function. + This means there is no need to pin the memory buffer for this method. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_NOTAVAILThe BASS_MUSIC_AUTOFREE flag is unavailable to decoding channels. + BASS_ERROR_FILEOPENThe file could not be opened. + BASS_ERROR_FILEFORMThe file's format is not recognised/supported. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_SPEAKERThe specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_NO3DCould not initialize 3D support. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + Away from Windows, all mixing is done in software (by BASS), so the BASS_SAMPLE_SOFTWARE flag is unnecessary. The BASS_SAMPLE_FX flag is also ignored. + DMO effects are not supported in MOD music on Windows CE, and DirectX 8 (or above) is required on Windows. They are always available on other platforms, except for the following: Compressor, Gargle, and I3DL2Reverb. When a DMO effect is unavailable, the MOD music can still be played, but the effect will be disabled. + + + The following example demontrates how to load music from memory: + + // Init Bass + Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero); + // open file + FileStream fs = File.OpenRead( "test.mod" ); + // get the length of the file + int length = (int)fs.Length; + // create the buffer which will keep the file in memory + byte[] buffer = new byte[length]; + // read the file into the buffer + fs.Read(buffer, 0, length); + // buffer is filled, file can be closed + fs.Close(); + // load music from memory buffer + int music = Bass.BASS_MusicLoad(buffer, 0, length, BASSFlag.BASS_DEFAULT, 0); + if (music != 0 && Bass.BASS_ChannelPlay(stream, false) ) + { + // playing... + } + else + { + Console.WriteLine("Error={0}", Bass.BASS_ErrorGetCode()); + } + + + ' Init Bass + Bass.BASS_Init(- 1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) + ' open file + Dim fs As FileStream = File.OpenRead("test.mod") + ' get the length of the file + Dim length As Integer = CInt(fs.Length) + ' create the buffer which will keep the file in memory + Dim buffer(length - 1) As Byte + ' read the file into the buffer + fs.Read(buffer, 0, length) + ' buffer is filled, file can be closed + fs.Close() + ' load music from memory buffer + Dim music As Integer = Bass.BASS_MusicLoad(buffer, 0, length, BASSFlag.BASS_DEFAULT, 0) + If music <> 0 AndAlso Bass.BASS_ChannelPlay(stream, False) Then + ' playing... + Else + Console.WriteLine("Error={0}", Bass.BASS_ErrorGetCode()) + End If + + + + + + Frees a MOD music's resources, including any sync/DSP/FX it has. + + The MOD music handle (which has been created with ). + If successful, is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + + Initializes a recording device. + + The device to use... -1 = default device, 0 = first. or can be used to get the total number of devices. + If successful, is returned, else is returned. Use BASS_ErrorGetCode to get the error code. + + This function must be successfully called before using the recording features. + Simultaneously using multiple devices is supported in the BASS API via a context switching system - instead of there being an extra "device" parameter in the function calls, the device to be used is set prior to calling the functions. is used to switch the current recording device. When successful, automatically sets the current thread's device to the one that was just initialized + When using the default device (device = -1), can be used to find out which device it was mapped to. On Windows, it'll always be the first device. + + + ERROR CODEDescription + BASS_ERROR_DXA sufficient version of DirectX is not installed. + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_ALREADYThe device has already been initialized. must be called before it can be initialized again. + BASS_ERROR_DRIVERThere is no available device driver. + + + Platform-specific + Recording support requires DirectX 5 (or above) on Windows. On Linux, a "Default" device is hardcoded to device number 0, which uses the default input set in the ALSA config; that could map directly to one of the other devices or it could use ALSA plugins. + + + + private RECORDPROC _myRecProc; // make it global, so that the GC can not remove it + private int _byteswritten = 0; + private byte[] _recbuffer; // local recording buffer + ... + if ( Bass.BASS_RecordInit(-1) ) + { + _myRecProc = new RECORDPROC(MyRecording); + int recHandle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, _myRecProc, IntPtr.Zero); + ... + // start recording + Bass.BASS_ChannelPlay(recHandle, false); + } + ... + private bool MyRecording(int handle, IntPtr buffer, int length, IntPtr user) + { + bool cont = true; + if (length > 0 && buffer != IntPtr.Zero) + { + // increase the rec buffer as needed + if (_recbuffer == null || _recbuffer.Length < length) + _recbuffer = new byte[length]; + // copy from managed to unmanaged memory + Marshal.Copy(buffer, _recbuffer, 0, length); + _byteswritten += length; + // write to file + ... + // stop recording after a certain amout (just to demo) + if (_byteswritten > 800000) + cont = false; // stop recording + } + return cont; + } + + + Private _myRecProc As RECORDPROC ' make it global, so that the GC can not remove it + Private _byteswritten As Integer = 0 + Private _recbuffer() As Byte ' local recording buffer + ... + If Bass.BASS_RecordInit(-1) Then + _myRecProc = New RECORDPROC(AddressOf MyRecording) + Dim recHandle As Integer = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, _myRecProc, IntPtr.Zero) + ... + ' start recording + Bass.BASS_ChannelPlay(recHandle, False) + End If + ... + Private Function MyRecording(handle As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Boolean + Dim cont As Boolean = True + If length > 0 AndAlso buffer <> IntPtr.Zero Then + ' increase the rec buffer as needed + If _recbuffer Is Nothing OrElse _recbuffer.Length < length Then + _recbuffer = New Byte(length) {} + End If + ' copy from managed to unmanaged memory + Marshal.Copy(buffer, _recbuffer, 0, length) + _byteswritten += length + ' write to file + ... + ' stop recording after a certain amout (just to demo) + If _byteswritten > 800000 Then + cont = False ' stop recording + End If + End If + Return cont + End Function + + If you are into C# you might also use an unsafe codeblock with native pointer access + (which might be must faster than the above - depending on what you are doing with the data): + + private unsafe bool MyRecording(int handle, IntPtr buffer, int length, IntPtr user) + { + bool cont = true; + if (length > 0 && buffer != IntPtr.Zero) + { + // assuming 16-bit sample data here + short *data = (short*)buffer; + ... + + // stop recording after a certain amout (just to demo) + if (_byteswritten > 800000) + cont = false; // stop recording + } + return cont; + } + + + + + + Starts recording. + + The sample rate to record at. + The number of channels... 1 = mono, 2 = stereo. + Any combination of these flags (see ) + + BASS_SAMPLE_8BITSUse 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the recorded data is 16-bit. + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers are required to use this flag in Windows. See Floating-point channels for more information. + BASS_RECORD_PAUSEStart the recording paused. Use together with the handle returned by this method to start it. + + + The user defined function to receive the recorded sample data... can be if you do not wish to use a callback. + User instance data to pass to the callback function. + If successful, the new recording's handle is returned, else is returned. Use BASS_ErrorGetCode to get the error code. + + Use to stop the recording, and to paused it. Recording can also be started in a paused state (via the BASS_RECORD_PAUSE flag), allowing DSP/FX to be set on it before any data reaches the callback function. + The sample data arrives from the recording device in chunks, so when specifying a very short period between callbacks, some calls may be skipped due to there being no new data available since the last call. + When not using a callback (proc = ), the recorded data is instead retrieved via . To keep latency at a minimum, the amount of data in the recording buffer should be monitored (also done via , with the BASS_DATA_AVAILABLE flag) to check that there is not too much data. + If there is too much data in the buffer, then that means the data currently being recorded will be delayed by the older data in the buffer being retrieved first. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_BUSYThe device is busy. An existing recording must be stopped before starting another one. Multiple simultaneous recordings can be made from the same device on Windows XP and Vista, but generally not on older Windows. + BASS_ERROR_NOTAVAILThe recording device is not available. Another application may already be recording with it, or it could be a half-duplex device and is currently being used for playback. + BASS_ERROR_FORMATThe specified format is not supported. If using the BASS_SAMPLE_FLOAT flag, it could be that floating-point recording is not supported. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + Multiple simultaneous recordings can be made from the same device on Windows XP and later, but generally not on older Windows. Multiple simultaneous recordings are possible on iOS/OSX/Windows CE, but may not be on Linux. + + + Start recording at 44100hz 16-bit stereo: + + private RECORDPROC _myRecProc; // make it global, so that the Garbage Collector can not remove it + ... + Bass.BASS_RecordInit(-1); + _myRecProc = new RECORDPROC(MyRecording); + // start recording paused + int recChannel = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, _myRecProc, IntPtr.Zero); + ... + // really start recording + Bass.BASS_ChannelPlay(recChannel, false); + ... + // the recording callback + private bool MyRecording(int handle, IntPtr buffer, int length, IntPtr user) + { + return true; + } + + + Private _myRecProc As RECORDPROC + ... + Bass.BASS_RecordInit(- 1) + _myRecProc = New RECORDPROC(AddressOf MyRecording) + ' start recording paused + Dim recChannel As Integer = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, _myRecProc, IntPtr.Zero) + ... + ' really start recording + Bass.BASS_ChannelPlay(recChannel, False) + ... + ' the recording callback + Private Function MyRecording(handle As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Boolean + Return True + End Function + + See for a recording callback sample. + + + + + Starts recording. + + The sample rate to record at. + The number of channels... 1 = mono, 2 = stereo. + Any combination of these flags (see ) + + BASS_SAMPLE_8BITSUse 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the recorded data is 16-bit. + BASS_SAMPLE_FLOATUse 32-bit floating-point sample data. WDM drivers are required to use this flag in Windows. See Floating-point channels for more information. + BASS_RECORD_PAUSEStart the recording paused. Use together with the handle returned by this method to start it. + + + Set the period (in milliseconds) between calls to the callback function (). The minimum period is 10ms, the maximum the maximum is half the BASS_CONFIG_REC_BUFFER setting. If the period specified is outside this range, it is automatically capped. + The user defined function to receive the recorded sample data... can be if you do not wish to use a callback. + User instance data to pass to the callback function. + If successful, the new recording's handle is returned, else is returned. Use BASS_ErrorGetCode to get the error code. + + Use to stop the recording. Recording can also be paused with . + When specifying a very short period between RECORDPROC calls, some calls may be skipped due to there being no new data available from the recording device since the last call. This is more likely to happen with drivers that do not have hardware support. + Starting the recording paused (BASS_RECORD_PAUSE) allows DSP/FX to be set on the recording channel before any data reaches the RECORDPROC function. + Not using a callback (proc = ) allows lower latency for full-duplex recording (ie. playing the data as it's being recorded), as you get the recorded data on demand via the function. To keep latency at a minimum, the amount of data in the recording buffer should be monitored (also done via , with the BASS_DATA_AVAILABLE flag) to check that there's not too much data. If there is too much data in the buffer, then that means the data currently being recorded will be delayed by the older data in the buffer being retrieved first. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called. + BASS_ERROR_BUSYThe device is busy. An existing recording must be stopped before starting another one. Multiple simultaneous recordings can be made from the same device on Windows XP and Vista, but generally not on older Windows. + BASS_ERROR_NOTAVAILThe recording device is not available. Another application may already be recording with it, or it could be a half-duplex device and is currently being used for playback. + BASS_ERROR_FORMATThe specified format is not supported. If using the BASS_SAMPLE_FLOAT flag, it could be that floating-point recording is not supported. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Start recording at 44100hz 16-bit stereo with a 50ms recording period: + + private RECORDPROC _myRecProc; // make it global, so that the Garbage Collector can not remove it + ... + Bass.BASS_RecordInit(-1); + _myRecProc = new RECORDPROC(MyRecording); + // start recording paused + int recChannel = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, 50, _myRecProc, IntPtr.Zero); + ... + // really start recording + Bass.BASS_ChannelPlay(recChannel, false); + ... + // the recording callback + private bool MyRecording(int handle, IntPtr buffer, int length, IntPtr user) + { + return true; + } + + + Private _myRecProc As RECORDPROC + ... + Bass.BASS_RecordInit(-1) + _myRecProc = New RECORDPROC(AddressOf MyRecording) + ' start recording paused + Dim recChannel As Integer = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, 50, _myRecProc, IntPtr.Zero) + ... + ' really start recording + Bass.BASS_ChannelPlay(recChannel, False) + ... + ' the recording callback + Private Function MyRecording(handle As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Boolean + Return True + End Function + + See for a recording callback sample. + + + + + + + + + + + + + Retrieves information on a recording device. + + The device to get the information of... 0 = first. + An instance of the class to store the information at. + If successful, then is returned, else is returned. Use to get the error code. + + This function can be used to enumerate the available recording devices for a setup dialog. + + + ERROR CODEDescription + BASS_ERROR_DEVICEThe device number specified is invalid. + BASS_ERROR_DXA sufficient version of DirectX is not installed. + + + Platform-specific + Recording support requires DirectX 5 (or above) on Windows. On Linux, a "Default" device is hardcoded to device number 0, which uses the default input set in the ALSA config. + + + List all available recording devices: + + BASS_DEVICEINFO info = new BASS_DEVICEINFO(); + for (int n=0; Bass.BASS_RecordGetDeviceInfo(n, info); n++) + { + Console.WriteLine(info.ToString()); + } + + + Dim n As Integer = 0 + Dim info As New BASS_DEVICEINFO() + While (Bass.BASS_RecordGetDeviceInfo(n, info)) + Console.WriteLine(info.ToString()) + n += 1 + End While + + Or use the method for more convenience. + + + + + Retrieves information on a recording device. + + The device to get the information of... 0 = first. + If successful, then an instance of the class is returned, else is returned. Use to get the error code. + + This function can be used to enumerate the available recording devices for a setup dialog. + + + ERROR CODEDescription + BASS_ERROR_DEVICEThe device number specified is invalid. + BASS_ERROR_DXA sufficient version of DirectX is not installed. + + + Platform-specific + Recording support requires DirectX 5 (or above) on Windows. On Linux, a "Default" device is hardcoded to device number 0, which uses the default input set in the ALSA config. + + Find the system default recording device: + + int defDevice = -1; + BASS_DEVICEINFO info; + for (int n = 0; (info = Bass.BASS_RecordGetDeviceInfo(n)) != null; n++) + { + if (info.IsDefault) + { + defDevice = n; + break; + } + } + + + Dim defDevice As Integer = -1 + Dim n As Integer = 0 + Dim info As New BASS_DEVICEINFO() + While Not (info Is Nothing) + info = Bass.BASS_RecordGetDeviceDescription(n) + If Not (info Is Nothing) And info.IsDefault Then + defDevice = n + Exit While + End If + n += 1 + End While + + Or use the method for more convenience. + + + + + Returns all available recording devices. + + An array of elements representing the available recording devices. + Uses internally. + + + + Returns the total number of available recording devices. + + Number of real recording devices available. + Uses internally. + + + + Sets the recording device to use for subsequent calls in the current thread. + + The device to use... 0 = first recording device. + If successful, then is returned, else is returned. Use to get the error code. + + Simultaneously using multiple devices is supported in the BASS API via a context switching system - instead of there being an extra "device" parameter in the function calls, the device to be used is set prior to calling the functions. The device setting is local to the current thread, so calling functions with different devices simultaneously in multiple threads is not a problem. + The functions that use the recording device selection are the following: + , , , , , . + When one of the above functions (or ) is called, BASS will check the current thread's recording device setting, and if no device is selected (or the selected device is not initialized), BASS will automatically select the lowest device that is initialized. + This means that when using a single device, there is no need to use this function - BASS will automatically use the device that's initialized. + Even if you free the device, and initialize another, BASS will automatically switch to the one that is initialized. + + + ERROR CODEDescription + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_INITThe device has not been initialized. + + + + + + + Retrieves the recording device setting in the current thread. + + If successful, the device number is returned, else -1 is returned. Use to get the error code. + See also . + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called - there are no initialized. + + + + + + + Retrieves information on the recording device being used. + + An instance of the class to store the information at. + If successful, is returned, else is returned. Use to get the error code. + There is no need to initialize any size member of the structure as described in the C/C++ interface, since all marchalling is already handled by the API here. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called - there are no initialized. + + + + + + BASS_RECORDINFO info = new BASS_RECORDINFO(); + bool ok = Bass.BASS_RecordGetInfo(info); + + + Dim info As New BASS_RECORDINFO() + Dim ok As Boolean = Bass.BASS_RecordGetInfo(info) + + + + + + Retrieves information on the recording device being used. + + An instance of the class on success - else . + There is no need to initialize any size member of the structure as described in the C/C++ interface, since all marchalling is already handled by the API here. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called - there are no initialized. + + + + + + BASS_RECORDINFO info = Bass.BASS_RecordGetInfo(info); + if (info != null) + Console.WriteLine(info.ToString()); + + + Dim info As BASS_RECORDINFO = Bass.BASS_RecordGetInfo(info) + If Not (info Is Nothing) Then + Console.WriteLine(info.ToString()) + End If + + + + + + + + + + + + + Retrieves the text description of a recording input source. + + The input to get the description of... 0 = first, -1 = master. + If succesful, then the description is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called - there are no initialized. + BASS_ERROR_ILLPARAM is invalid. + + + Platform-specific + On OSX, there is no master input (-1). + + + Get the name of the first input: + + string inputName = Bass.BASS_RecordGetInputName(0); + + + Dim inputName As String = Bass.BASS_RecordGetInputName(0) + + + + + + Returns all available recording input source names. + + An array of strings representing the available recording input source names. + Uses internally. + The index of the returned names equals the input-id, which might be used with . + + + + + Adjusts the settings of a recording input source. + + The input to adjust the settings of... 0 = first, -1 = master. + The new setting... a combination of these flags (): + + BASS_INPUT_OFFDisable the input. This flag can't be used when the device supports only one input at a time. + BASS_INPUT_ONEnable the input. If the device only allows one input at a time, then any previously enabled input will be disabled by this. + BASS_INPUT_NONEDon't change any setting. Use this flag, if you only want to set the volume. + + + The volume level... 0 (silent) to 1 (max), less than 0 = leave current. + If successful, is returned, else is returned. Use to get the error code. + + The actual volume level may not be exactly the same as requested, due to underlying precision differences. can be used to confirm what the volume is. + The volume curve used by this function is always linear, the BASS_CONFIG_CURVE_VOL config option setting has no effect on this. + Changes made by this function are system-wide, ie. other software using the device will be affected by it. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called - there are no initialized. + BASS_ERROR_ILLPARAM or is invalid. + BASS_NOTAVAILThe soundcard/driver doesn't allow you to change the input or it's volume. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + On OSX, there is no master input (-1), and only the currently enabled input has its volume setting available (if it has a volume control). + + + + // Disable the master input without changing the volume: + Bass.BASS_RecordSetInput(-1, BASSInput.BASS_INPUT_OFF, -1f ); + + // Enable the first input and set the volume to 50%: + Bass.BASS_RecordSetInput(0, BASSInput.BASS_INPUT_ON, 0.5f ); + + // Set the volume of the first input without changing the settings: + Bass.BASS_RecordSetInput(0, BASSInput.BASS_INPUT_NONE, 1f ); + + + ' Disable the master input without changing the volume: + Bass.BASS_RecordSetInput(-1, BASSInput.BASS_INPUT_OFF, -1F) + + ' Enable the first input and set the volume to 50%: + Bass.BASS_RecordSetInput(0, BASSInput.BASS_INPUT_ON, 0.5F) + + ' Set the volume of the first input without changing the settings: + Bass.BASS_RecordSetInput(0, BASSInput.BASS_INPUT_NONE, 1F ); + + + + + + Retrieves the settings of a recording input source. + + The input to get the settings of... 0 = first, -1 = master. + Reference to a variable to receive the current volume. + If an error occurs, -1 is returned, use to get the error code. + If successful, then the settings are returned. The BASS_INPUT_OFF flag will be set if the input is disabled, + otherwise the input is enabled. The type of input (see ) is also indicated in the high 8-bits (use BASS_INPUT_TYPE_MASK to test) of the return value, + and can be one of the following. If the volume is requested but not available, volume will receive -1. + + BASS_INPUT_TYPE_DIGITALDigital input source, for example, a DAT or audio CD. + BASS_INPUT_TYPE_LINELine-in. On some devices, "Line-in" may be combined with other analog sources into a single BASS_INPUT_TYPE_ANALOG input. + BASS_INPUT_TYPE_MICMicrophone. + BASS_INPUT_TYPE_SYNTHInternal MIDI synthesizer. + BASS_INPUT_TYPE_CDAnalog audio CD. + BASS_INPUT_TYPE_PHONETelephone. + BASS_INPUT_TYPE_SPEAKERPC speaker. + BASS_INPUT_TYPE_WAVEThe device's WAVE/PCM output. + BASS_INPUT_TYPE_AUXAuxiliary. Like "Line-in", "Aux" may be combined with other analog sources into a single BASS_INPUT_TYPE_ANALOG input on some devices. + BASS_INPUT_TYPE_ANALOGAnalog, typically a mix of all analog sources. + BASS_INPUT_TYPE_UNDEFAnything that is not covered by the other types. + + + + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called - there are no initialized. + BASS_ERROR_ILLPARAM is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + The input type information is only available on Windows. There is no "what you hear" type of input defined; if the device has one, it will typically come under BASS_INPUT_TYPE_ANALOG or BASS_INPUT_TYPE_UNDEF. + On OSX, there is no master input (-1), and only the currently enabled input has its volume setting available (if it has a volume control). + + + List all available input sources, with their current status: + + Bass.BASS_RecordInit(-1); // init the default device + string name; + for (int n = 0; (name = Bass.BASS_RecordGetInputName(n)) != null; n++) + { + float vol = 0f; + int setting = Bass.BASS_RecordGetInput(n, ref vol); + Console.WriteLine("{0} [{1} : {2}] - {3}", + name, + (BASSInputType)((int)BASSInputType.BASS_INPUT_TYPE_MASK & setting), + vol, + ((int)BASSInput.BASS_INPUT_OFF & setting) != 0 ? "Off" : "On"); + } + + + Bass.BASS_RecordInit(-1) ' init the default device + Dim n As Integer = 0 + Dim name As String = "" + While Not (name Is Nothing) + name = Bass.BASS_RecordGetInputName(n) + n += 1 + If Not (name Is Nothing) Then + Dim vol As Single = 0F + Dim setting As Integer = Bass.BASS_RecordGetInput(n, vol) + Console.WriteLine("{0} [{1} : {2}] - {3}", + name, + CType(CInt(BASSInputType.BASS_INPUT_TYPE_MASK) And setting, BASSInputType), + vol, + CStr(IIf(CInt(BASSInput.BASS_INPUT_OFF) And setting <> 0, "Off", "On"))) + End If + End While + + Find a microphone input: + + Bass.BASS_RecordInit(-1); + int mic = -1; + int n = 0; + int settings = 0; + float vol = 0f; + while (settings != -1) + { + // get the settings of that input + settings = Bass.BASS_RecordGetInput(n, ref vol); + if ( (settings & (int)BASSInputType.BASS_INPUT_TYPE_MASK) == (int)BASSInputType.BASS_INPUT_TYPE_MIC ) + { + // found the mic! + mic = n; + break; + } + n++; + } + if (mic != -1) + Console.WriteLine( "Found a MIC at input {0}", mic ); + else + Console.WriteLine( "No MIC found!" ); + + + Bass.BASS_RecordInit(-1) + Dim mic As Integer = -1 + Dim n As Integer = 0 + Dim settings As Integer = 0 + Dim vol As Single = 0F + While settings <> -1 + ' get the settings of that input + settings = Bass.BASS_RecordGetInput(n, vol) + If (settings And CInt(BASSInputType.BASS_INPUT_TYPE_MASK)) = CInt(BASSInputType.BASS_INPUT_TYPE_MIC) Then + ' found the mic! + mic = n + Exit While + End If + n += 1 + End While + If mic <> -1 Then + Console.WriteLine("Found a MIC at input {0}", mic) + Else + Console.WriteLine("No MIC found!") + End If + + + + + + Retrieves the setting of a recording input source. + + The input to get the settings of... 0 = first, -1 = master. + One of the values (BASS_INPUT_NONE on error). + returns both, the (in the high-word) + as well as the (in the low-word). + Use this overload to only retrieve the without the . + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called - there are no initialized. + BASS_ERROR_ILLPARAM is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + The input type information is only available on Windows. There is no "what you hear" type of input defined; if the device has one, it will typically come under BASS_INPUT_TYPE_ANALOG or BASS_INPUT_TYPE_UNDEF. + On OSX, there is no master input (-1), and only the currently enabled input has its volume setting available (if it has a volume control). + + + + + + + + + + + + + Retrieves the type of input of a recording input source. + + The input to get the settings of... 0 = first, -1 = master. + One of the values (BASS_INPUT_TYPE_ERROR on error). + returns both, the (in the high-word) + as well as the (in the low-word). + Use this overload to only retrieve the without the . + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called - there are no initialized. + BASS_ERROR_ILLPARAM is invalid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + The input type information is only available on Windows. There is no "what you hear" type of input defined; if the device has one, it will typically come under BASS_INPUT_TYPE_ANALOG or BASS_INPUT_TYPE_UNDEF. + On OSX, there is no master input (-1), and only the currently enabled input has its volume setting available (if it has a volume control). + + + Find a microphone input: + + Bass.BASS_RecordInit(-1); // init the default device + int mic = -1; + BASSInputType flags; + for (int n=0; (flags=Bass.BASS_RecordGetInputType(n)) != BASSInputType.BASS_INPUT_TYPE_ERROR; n++) + { + if ( (flags & BASSInputType.BASS_INPUT_TYPE_MASK) == BASSInputType.BASS_INPUT_TYPE_MIC ) + { + // found the mic! + mic = n; + break; + } + } + if (mic != -1) + Console.WriteLine( "Found a MIC at input {0}", mic ); + else + Console.WriteLine( "No MIC found!" ); + + + Bass.BASS_RecordInit(- 1) + Dim mic As Integer = -1 + Dim n As Integer = 0 + Dim flags As BASSInputType = BASSInputType.BASS_INPUT_TYPE_UNDEF + While flags <> BASSInputType.BASS_INPUT_TYPE_ERROR + ' get the settings of that input + flags = Bass.BASS_RecordGetInputType(n) + If (flags And BASSInputType.BASS_INPUT_TYPE_MASK) = BASSInputType.BASS_INPUT_TYPE_MIC) Then + ' found the mic! + mic = n + Exit While + End If + n += 1 + End While + If mic <> -1 Then + Console.WriteLine("Found a MIC at input {0}", mic) + Else + Console.WriteLine("No MIC found!") + End If + + + + + + Frees all resources used by the recording device. + + If successful, then is returned, else is returned. Use to get the error code. + + This function should be called for all initialized recording devices before your program exits. + When using multiple recording devices, the current thread's device setting (as set with ) determines which device this function call applies to. + + + ERROR CODEDescription + BASS_ERROR_INIT has not been successfully called - there are no initialized. + + + + + + + Retrieves information on a channel. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM, or HRECORD. + instance where to store the channel information at. + If successful, is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + Getting the channel info: + + BASS_CHANNELINFO info = new BASS_CHANNELINFO(); + Bass.BASS_ChannelGetInfo(_stream, info); + Console.WriteLine( info.ToString() ); + + + Dim info As New BASS_CHANNELINFO() + Bass.BASS_ChannelGetInfo(_stream, info) + Console.WriteLine(info.ToString()) + + + + + + Retrieves information on a channel. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM, or HRECORD. + An instance of the class on success - else . + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + Getting the channel info: + + BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(_stream); + Console.WriteLine( info.ToString() ); + + + Dim info As BASS_CHANNELINFO = Bass.BASS_ChannelGetInfo(_stream) + Console.WriteLine(info.ToString()) + + + + + + Starts (or resumes) playback of a sample, stream, MOD music, or recording. + + The channel handle... a HCHANNEL / HMUSIC / HSTREAM / HRECORD handle. + Restart playback from the beginning? If handle is a user stream, it's current buffer contents are flushed. If it's a MOD music, it's BPM/etc are automatically reset to their initial values. + If successful, is returned, else is returned. Use to get the error code. + + When streaming in blocks (BASS_STREAM_BLOCK), the restart parameter is ignored as it's not possible to go back to the start. The parameter is also of no consequence with recording channels. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_STARTThe output is paused/stopped, use to start it. + BASS_ERROR_DECODEThe channel is not playable, it's a "decoding channel". + BASS_ERROR_BUFLOSTShould not happen... check that a valid window handle was used with . + BASS_ERROR_NOHWNo hardware voices are available (HCHANNEL only). This only occurs if the sample was loaded/created with the BASS_SAMPLE_VAM flag, and BASS_VAM_HARDWARE is set in the sample's VAM mode, and there are no hardware voices available to play it. + + + + + + Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero); + // create the stream + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_DEFAULT); + Bass.BASS_ChannelPlay(stream, false); + ... + Bass.BASS_StreamFree(stream); + + + Bass.BASS_Init(- 1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero) + ' create the stream + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_DEFAULT) + Bass.BASS_ChannelPlay(stream, False) + ... + Bass.BASS_StreamFree(stream) + + + + + + Sets up a user DSP function on a stream, MOD music, or recording channel. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + The callback function (see ). + User instance data to pass to the callback function. + The priority of the new DSP, which determines it's position in the DSP chain - DSPs with higher priority are called before those with lower. + If succesful, then the new DSP's handle is returned, else 0 is returned. Use to get the error code. + + The channel does not have to be playing to set a DSP function, they can be set before and while playing. + Equally, you can also remove them at any time. Use to remove a DSP function. + Multiple DSP functions may be used per channel, in which case the order that the functions are called is determined by their priorities. Any DSPs that have the same priority are called in the order that they were added. + DSP functions can be applied to MOD musics and streams, but not samples. If you want to apply a DSP function to a sample, then you should stream the sample. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + + + + + The following example shows a little gain amplifier, assuming you are processing 32-bit BASS_SAMPLE_FLOAT! + + private float _gainDB = 0f; + private int _stream = 0; + private DSPPROC _myDSPProc; // make it global, so that the GC can not remove it + ... + _gainDB = 6f; // amplify by +6dB + _stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, + BASSFlag.BASS_STREAM_AUTOFREE | BASSFlag.BASS_SAMPLE_FLOAT); + // set a DSP user callback method + _myDSPProc = new DSPPROC(MyDSPGain); + // set the user DSP callback + Bass.BASS_ChannelSetDSP(_stream, _myDSPProc, IntPtr.Zero, 0); + ... + // this is the actual processing method + private void MyDSPGain(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + // the global variable _gainDB contains the amplification value in dB! + if (_gainDB == 0f || length == 0 || buffer == IntPtr.Zero) + return; + + // convert the _gainDB value to a float + float _gainAmplification = (float)Math.Pow(10d, _gainDB / 20d); + // number of bytes in 32-bit floats, since length is in bytes + int l4 = length/4; + float[] data = new float[l4]; + // copy from managed to unmanaged memory + Marshal.Copy(buffer, data, 0, l4); + // apply gain, assumeing using 32-bit floats (no clipping here ;-) + for (int a=0; a<l4; a++) + data[a] = data[a] * _gainAmplification; + // copy back from unmanaged to managed memory + Marshal.Copy(data, 0, buffer, l4); + } + + + Private _gainDB As Single = 0F + Private _stream As Integer = 0 + Private _myDSPProc As DSPPROC ' make it global, so that the GC can not remove it + ... + _gainDB = 6f; // amplify by +6dB + _stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, + BASSFlag.BASS_STREAM_AUTOFREE Or BASSFlag.BASS_SAMPLE_FLOAT) + ' set a DSP user callback method + _myDSPProc = New DSPPROC(AddressOf MyDSPGain) + ' set the user DSP callback + Bass.BASS_ChannelSetDSP(_stream, _myDSPProc, IntPtr.Zero, 0) + ... + ' this is the actual processing method + Private Sub MyDSPGain(handle As Integer, channel As Integer, + buffer As IntPtr, length As Integer, user As IntPtr) + ' the global variable _gainDB contains the amplification value in dB! + If _gainDB = 0F OrElse length = 0 OrElse buffer = IntPtr.Zero Then + Return + End If + ' convert the _gainDB value to a float + Dim _gainAmplification As Single = CSng(Math.Pow(10.0, _gainDB / 20.0)) + ' number of bytes in 32-bit floats, since length is in bytes + Dim l4 As Integer = length / 4 + Dim data(l4 - 1) As Single + ' copy from managed to unmanaged memory + Marshal.Copy(buffer, data, 0, l4) + ' apply gain, assumeing using 32-bit floats (no clipping here ;-) + Dim a As Integer + For a = 0 To l4 - 1 + data(a) = data(a) * _gainAmplification + Next a + ' copy back from unmanaged to managed memory + Marshal.Copy(data, 0, buffer, l4) + End Sub + + This example is type safe but 'slow', since two copy operations are involved. + One from unmanaged BASS to managed .NET and when processing has been done locally from .NET back to BASS. + However, for VB.Net users this is almost the only way to do it. + C# user can be a little more lucky, since C# supports unsafe code blocks and native pointer access - + which will be shown in the following example: + + private unsafe void MyDSPGain(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + if (_gainDB == 1f || length == 0 || buffer == IntPtr.Zero) + return; + + // convert the _gainDB value to a float + float _gainAmplification = (float)Math.Pow(10d, _gainDB / 20d); + // length is in bytes, so the number of floats to process is length/4 + int l4 = length / 4; + // cast the given buffer IntPtr to a native pointer to float values + float *data = (float*)buffer; + for (int a=0; a<l4; a++) + { + data[a] = data[a] * _gainAmplification; + // alternatively you can also use: + // *data = *data * _gainAmplification; + // data++; + } + } + + + + + + Retrieves the immediate sample data (or an FFT representation of it) of a sample channel, stream, MOD music, or recording channel. + This overload uses an IntPtr to reference the buffer data. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM, or HRECORD. + Location to write the data as an IntPtr (can be when handle is a recording channel (HRECORD), to discard the requested amount of data from the recording buffer). + Use "Marshal.AllocCoTaskMem" to allocate a memory buffer, use "Marshal.Copy" to copy the buffer data from unmanaged BASS to your managed code and use "Marshal.FreeCoTaskMem" to free the memory buffer when not needed anymore. + Or make use of a "GCHandle" to receive data to a pinned managed object. + + Number of bytes wanted, and/or the following flags (): + + BASS_DATA_FLOATReturn floating-point sample data. + BASS_DATA_FFT256256 sample FFT (returns 128 floating-point values) + BASS_DATA_FFT512512 sample FFT (returns 256 floating-point values) + BASS_DATA_FFT10241024 sample FFT (returns 512 floating-point values) + BASS_DATA_FFT20482048 sample FFT (returns 1024 floating-point values) + BASS_DATA_FFT40964096 sample FFT (returns 2048 floating-point values) + BASS_DATA_FFT81928192 sample FFT (returns 4096 floating-point values) + BASS_DATA_FFT1638416384 sample FFT (returns 8192 floating-point values) + BASS_DATA_FFT_INDIVIDUALPerform a separate FFT for each channel, rather than a single combined FFT. The size of the data returned (as listed above) is multiplied by the number of channels. + BASS_DATA_FFT_NOWINDOWPrevent a Hann window being applied to the sample data when performing an FFT. + BASS_DATA_FFT_REMOVEDCRemove any DC bias from the sample data when performing an FFT. + BASS_DATA_AVAILABLEQuery the amount of data the channel has buffered. This flag is primarily of use when recording, and can't be used with decoding channels as they do not have playback buffers. buffer can be when using this flag. + + + If an error occurs, -1 is returned, use to get the error code. + When requesting FFT data, the number of bytes read from the channel (to perform the FFT) is returned. + When requesting sample data, the number of bytes written to buffer will be returned (not necessarily the same as the number of bytes read when using the BASS_DATA_FLOAT flag). + When using the BASS_DATA_AVAILABLE flag, the number of bytes in the channel's buffer is returned. + + + This function can only return as much data as has been written to the channel's buffer, so it may not always be possible to get the amount of data requested, especially if you request large amounts. If you really do need large amounts, then increase the buffer lengths (BASS_CONFIG_BUFFER). + The BASS_DATA_AVAILABLE flag can be used to check how much data a channel's buffer contains at any time, including when stopped or stalled. + When requesting data from a "decoding channel" (BASS_STREAM_DECODE or BASS_MUSIC_DECODE was used at creation), there are no intermediate buffers involved, so as much data as is available can be decoded in one go. + When retrieving sample data, the returned data is in the standard Windows PCM format: 8-bit samples are unsigned, 16-bit samples are signed, 32-bit floating-point samples range from -1 to 1 (not clipped, so can actually be outside this range). That's unless the BASS_DATA_FLOAT flag is used, in which case, the sample data will be converted to 32-bit floating-point (if it isn't already). + When requesting FFT data, floating-point values ranging from 0 to 1 are returned. Only the first half of the FFT is useful, so that's what BASS returns. For example with a 2048 sample FFT, it'll return 1024 values - the 1st value being the DC component, the 2nd the amplitude at 1/2048 of the channel's sample rate, then the amplitude at 2/2048, 3/2048, etc... + A Hanning window is applied to the sample data to reduce leakage, unless the BASS_DATA_FFT_NOWINDOW flag is used. When a window is applied, it causes the DC component to leak into the next bin, but that can be removed (reduced to 0) by using the BASS_DATA_FFT_REMOVEDC flag. Doing so slightly increases the processing required though, so it should only be done when needed, which is when a window is applied and the 2nd bin value is important. + Channels that have 2 or more sample channels (ie. stereo or above) may have FFT performed on each individual channel, using the BASS_DATA_FFT_INDIVIDUAL flag. Without this flag, all the channels are combined, and a single mono FFT is performed. Performing the extra individual FFTs of course increases the amount of processing required. The return values are interleaved in the same order as the channel's sample data, eg. stereo = left,right,left,etc... + This function is most useful if you wish to visualize (eg. spectrum analyze) the sound. + FFT processing hint 1: DC stands for direct current (same as what a flashlight cell gives out) and is represents a 0 Hz sound, which cannot exist in real life. A sound sample should not have any DC component but probably will due to inaccuracies in the recording equipment. You won't hear it (except a click when playing and stopping the sample). + The DC component is basically the average of all the samples that the FFT was applied to, and is pretty useless. + You'll have to halve the DC component that BASS returns to get the actual DC component, as BASS doubles all the bin values. + + FFT processing hint 2: How to read out the amplitude of a single frequency/a frequency band? + FFT[0] maps to amplitude at 0 Hz, FFT[length-1] maps to amplitude at Nyquist's frequency. So the index to FFT data at an arbitrary band is: + + idx = length*freq/Nyquist + where: + length : length of the returned FFT buffer (in samples) + freq : required frequency (Hz) + Nyquist : Nyquist's frequency of the signal (half the sampling rate) (in Hz) + + Example: If the stream is 44100Hz, then 16500Hz will be around bin 191 of a 512 sample FFT (512*16500/44100). + Or, if you are using BASS_DATA_FFT4096 on a stream with a sample rate of 44100 a tone at 540Hz will be at: 540*4096/44100 = 50.15, so a bit of the energy will be in fft[51], but mostly in fft[50]. + Note: With a sample rate of 44100 the Nyquist frequency is 22050Hz, which is the max. frequency. This is also why BASS_DATA_FFT4096 only returns 2048 values - fft[2048] would represent 22050Hz. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_ENDEDThe channel has reached the end. + BASS_ERROR_NOTAVAILThe BASS_DATA_AVAILABLE flag was used with a decoding channel. + BASS_ERROR_BUFLOSTShould not happen... check that a valid window handle was used with . + + + + + The following example assumes that you have created the stream with the BASS_SAMPLE_FLOAT flag. + So the buffer will contain 32-bit values between -1 and 1...as an array of float: + + // a 30ms window in bytes to be filled with sample data + int length = (int)Bass.BASS_ChannelSeconds2Bytes(channel, 0.03); + + // first we need a mananged object where the sample data should be held + // only length/4 elements needed, since length is in byte and a float uses 4 bytes + float[] data = new float[length/4]; + + // create a pinned handle to a managed object + GCHandle hGC = GCHandle.Alloc(data, GCHandleType.Pinned); + + // get the data + length = Bass.BASS_ChannelGetData(channel, hGC.AddrOfPinnedObject(), length); + + // free the pinned handle + hGC.Free(); + + + ' a 30ms window in bytes to be filled with sample data + Dim length As Integer = CInt(Bass.BASS_ChannelSeconds2Bytes(channel, 0.03)) + + ' first we need a mananged object where the sample data should be held + ' only length/4 elements needed, since length is in byte and a float uses 4 bytes + Dim data(length/4 - 1) As Single + + ' create a pinned handle to a managed object + Dim hGC As GCHandle = GCHandle.Alloc(data, GCHandleType.Pinned) + + ' get the data + length = Bass.BASS_ChannelGetData(channel, hGC.AddrOfPinnedObject(), length) + + ' free the pinned handle + hGC.Free() + + A more simple way is to use the other overloads where you simply pass the array itself + (those overloads pass the buffer array as a reference type by value with automatic pinning, + which is as fast as the following example). + If you are into C# you might even use native pointers in an unsafe code block: + + // a 30ms window in bytes to be filled with sample data + int length = (int)Bass.BASS_ChannelSeconds2Bytes(channel, 0.03); + + // first we need a mananged object where the sample data should be held + // only length/4 elements needed, since length is in byte and a float uses 4 bytes + float[] data = new float[length/4]; + + // start an unsafe code block allowing you to use native pointers + unsafe + { + // pointers to managed objects need to be fixed + fixed (float* buffer = data) // equivalent to buffer = &data[0] + { + length = Bass.BASS_ChannelGetData(channel, (IntPtr)buffer, length); + } + } + + This is by far the fastest way to use BASS_ChannelGetData, but unfortunately not availabe with VB.Net. + However, the other overloads do automatically pin the buffer as needed and are as fast as this. + + + + + Retrieves the immediate sample data (or an FFT representation of it) of a sample channel, stream, MOD music, or recording channel. + This overload uses a managed float[] to reference the buffer data as 32-bit! + SHOULD ONLY BE USED, if the stream was created with BASS_SAMPLE_FLOAT! + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM, or HRECORD. + The array (float[]) to receive the data, use BASS_SAMPLE_FLOAT when creating the channel stream! + Number of bytes wanted, and/or the following flags (): + + BASS_DATA_FLOATReturn floating-point sample data. + BASS_DATA_FFT256256 sample FFT (returns 128 floating-point values) + BASS_DATA_FFT512512 sample FFT (returns 256 floating-point values) + BASS_DATA_FFT10241024 sample FFT (returns 512 floating-point values) + BASS_DATA_FFT20482048 sample FFT (returns 1024 floating-point values) + BASS_DATA_FFT40964096 sample FFT (returns 2048 floating-point values) + BASS_DATA_FFT81928192 sample FFT (returns 4096 floating-point values) + BASS_DATA_FFT1638416384 sample FFT (returns 8192 floating-point values) + BASS_DATA_FFT_INDIVIDUALPerform a separate FFT for each channel, rather than a single combined FFT. The size of the data returned (as listed above) is multiplied by the number of channels. + BASS_DATA_FFT_NOWINDOWPrevent a Hann window being applied to the sample data when performing an FFT. + BASS_DATA_FFT_REMOVEDCRemove any DC bias from the sample data when performing an FFT. + BASS_DATA_AVAILABLEQuery the amount of data the channel has buffered. This flag is primarily of use when recording, and can't be used with decoding channels as they do not have playback buffers. buffer can be when using this flag. + + + If an error occurs, -1 is returned, use to get the error code. + When requesting FFT data, the number of bytes read from the channel (to perform the FFT) is returned. + When requesting sample data, the number of bytes written to buffer will be returned (not necessarily the same as the number of bytes read when using the BASS_DATA_FLOAT flag). + When using the BASS_DATA_AVAILABLE flag, the number of bytes in the channel's buffer is returned. + + + This function can only return as much data as has been written to the channel's buffer, so it may not always be possible to get the amount of data requested, especially if you request large amounts. If you really do need large amounts, then increase the buffer lengths (BASS_CONFIG_BUFFER). + The BASS_DATA_AVAILABLE flag can be used to check how much data a channel's buffer contains at any time, including when stopped or stalled. + When requesting data from a "decoding channel" (BASS_STREAM_DECODE or BASS_MUSIC_DECODE was used at creation), there are no intermediate buffers involved, so as much data as is available can be decoded in one go. + When retrieving sample data, the returned data is in the standard Windows PCM format: 8-bit samples are unsigned, 16-bit samples are signed, 32-bit floating-point samples range from -1 to 1 (not clipped, so can actually be outside this range). That's unless the BASS_DATA_FLOAT flag is used, in which case, the sample data will be converted to 32-bit floating-point (if it isn't already). + When requesting FFT data, floating-point values ranging from 0 to 1 are returned. Only the first half of the FFT is useful, so that's what BASS returns. For example with a 2048 sample FFT, it'll return 1024 values - the 1st value being the DC component, the 2nd the amplitude at 1/2048 of the channel's sample rate, then the amplitude at 2/2048, 3/2048, etc... + A Hanning window is applied to the sample data to reduce leakage, unless the BASS_DATA_FFT_NOWINDOW flag is used. When a window is applied, it causes the DC component to leak into the next bin, but that can be removed (reduced to 0) by using the BASS_DATA_FFT_REMOVEDC flag. Doing so slightly increases the processing required though, so it should only be done when needed, which is when a window is applied and the 2nd bin value is important. + Channels that have 2 or more sample channels (ie. stereo or above) may have FFT performed on each individual channel, using the BASS_DATA_FFT_INDIVIDUAL flag. Without this flag, all the channels are combined, and a single mono FFT is performed. Performing the extra individual FFTs of course increases the amount of processing required. The return values are interleaved in the same order as the channel's sample data, eg. stereo = left,right,left,etc... + This function is most useful if you wish to visualize (eg. spectrum analyze) the sound. + FFT processing hint 1: DC stands for direct current (same as what a flashlight cell gives out) and is represents a 0 Hz sound, which cannot exist in real life. A sound sample should not have any DC component but probably will due to inaccuracies in the recording equipment. You won't hear it (except a click when playing and stopping the sample). + The DC component is basically the average of all the samples that the FFT was applied to, and is pretty useless. + You'll have to halve the DC component that BASS returns to get the actual DC component, as BASS doubles all the bin values. + + FFT processing hint 2: How to read out the amplitude of a single frequency/a frequency band? + FFT[0] maps to amplitude at 0 Hz, FFT[length-1] maps to amplitude at Nyquist's frequency. So the index to FFT data at an arbitrary band is: + + idx = length*freq/Nyquist + where: + length : length of the returned FFT buffer (in samples) + freq : required frequency (Hz) + Nyquist : Nyquist's frequency of the signal (half the sampling rate) (in Hz) + + Example: If the stream is 44100Hz, then 16500Hz will be around bin 191 of a 512 sample FFT (512*16500/44100). + Or, if you are using BASS_DATA_FFT4096 on a stream with a sample rate of 44100 a tone at 540Hz will be at: 540*4096/44100 = 50.15, so a bit of the energy will be in fft[51], but mostly in fft[50]. + Note: With a sample rate of 44100 the Nyquist frequency is 22050Hz, which is the max. frequency. This is also why BASS_DATA_FFT4096 only returns 2048 values - fft[2048] would represent 22050Hz. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_ENDEDThe channel has reached the end. + BASS_ERROR_NOTAVAILThe BASS_DATA_AVAILABLE flag was used with a decoding channel. + BASS_ERROR_BUFLOSTShould not happen... check that a valid window handle was used with . + + + + + The following example assumes that you have created the stream with the BASS_SAMPLE_FLOAT flag. + So the buffer will contain 32-bit values between -1 and 1...as an array of float: + + // a 30ms window in bytes to be filled with sample data + int length = (int)Bass.BASS_ChannelSeconds2Bytes(channel, 0.03); + + // first we need a mananged object where the sample data should be placed + // length is in bytes, so the number of floats to process is length/4 + float[] data = new float[length/4]; + + // get the sample data + length = Bass.BASS_ChannelGetData(channel, data, length); + + + ' a 30ms window in bytes to be filled with sample data + Dim length As Integer = CInt(Bass.BASS_ChannelSeconds2Bytes(channel, 0.03)) + + ' first we need a mananged object where the sample data should be placed + ' length is in bytes, so the number of floats to process is length/4 + Dim data(length/4 - 1) As Single + + ' get the sample data + length = Bass.BASS_ChannelGetData(channel, data, length) + + The next example will gather the immediate FFT data from a channel: + + float[] fft = new float[2048]; + Bass.BASS_ChannelGetData(channel, fft, (int)BASSData.BASS_DATA_FFT4096) + // assuming the channel's samplerate is 44.1kHz, + // this will return the frequency represented by bucket 51 + int hz = Utils.FFTIndex2Frequency(51, 4096, 44100); + + + Dim fft(2048 - 1) As Single + Bass.BASS_ChannelGetData(channel, fft, CInt(BASSData.BASS_DATA_FFT4096)) + ' assuming the channel's samplerate is 44.1kHz, + ' this will return the frequency represented by bucket 51 + Dim hz As Integer = Utils.FFTIndex2Frequency(51, 4096, 44100) + + + + + + Retrieves the immediate sample data of a sample channel, stream, MOD music, or recording channel. + This overload uses a managed short[] to reference the buffer data as 16-bit values - each element will represent one channel in this case! + SHOULD ONLY BE USED, if the stream was created WITHOUT BASS_SAMPLE_FLOAT or BASS_SAMPLE_8BITS! + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM, or HRECORD. + The array (short[]) to receive the data, e.g. when creating the channel stream with default setting, meaning 16-bit samples! + Number of bytes wanted, and/or the following flags (): + + BASS_DATA_AVAILABLEQuery the amount of data the channel has buffered. This flag is primarily of use when recording, and can't be used with decoding channels as they do not have playback buffers. buffer can be when using this flag. + + + If an error occurs, -1 is returned, use to get the error code. + When requesting sample data, the number of bytes written to buffer will be returned (not necessarily the same as the number of bytes read). + When using the BASS_DATA_AVAILABLE flag, the number of bytes in the channel's buffer is returned. + + + This function can only return as much data as has been written to the channel's buffer, so it may not always be possible to get the amount of data requested, especially if you request large amounts. If you really do need large amounts, then increase the buffer lengths (BASS_CONFIG_BUFFER). + The BASS_DATA_AVAILABLE flag can be used to check how much data a channel's buffer contains at any time, including when stopped or stalled. + When requesting data from a "decoding channel" (BASS_STREAM_DECODE or BASS_MUSIC_DECODE was used at creation), there are no intermediate buffers involved, so as much data as is available can be decoded in one go. + When retrieving sample data, the returned data is in the standard Windows PCM format: 8-bit samples are unsigned, 16-bit samples are signed, 32-bit floating-point samples range from -1 to 1 (not clipped, so can actually be outside this range). That's unless the BASS_DATA_FLOAT flag is used, in which case, the sample data will be converted to 32-bit floating-point (if it isn't already). + This function is most useful if you wish to visualize (eg. spectrum analyze) the sound. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_ENDEDThe channel has reached the end. + BASS_ERROR_NOTAVAILThe BASS_DATA_AVAILABLE flag was used with a decoding channel. + BASS_ERROR_BUFLOSTShould not happen... check that a valid window handle was used with . + + + + + The following example assumes that you have created the stream with the BASS_DEFAULT flag. + So the buffer will contain 16-bit values...as an array of short values. + + // a 30ms window in bytes to be filled with sample data + int length = (int)Bass.BASS_ChannelSeconds2Bytes(channel, 0.03); + + // first we need a mananged object where the sample data should be placed + // length is in bytes, so the number of shorts to process is length/2 + short[] data = new short[length/2]; + + // get the sample data + length = Bass.BASS_ChannelGetData(channel, data, length); + + + ' a 30ms window in bytes to be filled with sample data + Dim length As Integer = CInt(Bass.BASS_ChannelSeconds2Bytes(channel, 0.03)) + + ' first we need a mananged object where the sample data should be placed + ' length is in bytes, so the number of floats to process is length/2 + Dim data(length/2 -1) As Short + + ' get the sample data + length = Bass.BASS_ChannelGetData(channel, data, length) + + + + + + Retrieves the immediate sample data of a sample channel, stream, MOD music, or recording channel. + This overload uses a managed int[] to reference the buffer data (Note: an int is 32-bit meaning if we expect to receive 16-bit data stereo a single int value will contain 2 x 16-bit, so a full stereo pair of data)! + SHOULD ONLY BE USED, if the stream was created WITHOUT BASS_SAMPLE_FLOAT or BASS_SAMPLE_8BITS! + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM, or HRECORD. + The array (int[]) to receive the data, e.g. when creating the channel stream with default setting, meaning 16-bit samples, an int value contains 2 channels (left and right)! + Number of bytes wanted, and/or the following flags (): + + BASS_DATA_AVAILABLEQuery the amount of data the channel has buffered. This flag is primarily of use when recording, and can't be used with decoding channels as they do not have playback buffers. buffer can be when using this flag. + + + If an error occurs, -1 is returned, use to get the error code. + When requesting sample data, the number of bytes written to buffer will be returned (not necessarily the same as the number of bytes read when using the BASS_DATA_FLOAT flag). + When using the BASS_DATA_AVAILABLE flag, the number of bytes in the channel's buffer is returned. + + + This function can only return as much data as has been written to the channel's buffer, so it may not always be possible to get the amount of data requested, especially if you request large amounts. If you really do need large amounts, then increase the buffer lengths (BASS_CONFIG_BUFFER). + The BASS_DATA_AVAILABLE flag can be used to check how much data a channel's buffer contains at any time, including when stopped or stalled. + When requesting data from a "decoding channel" (BASS_STREAM_DECODE or BASS_MUSIC_DECODE was used at creation), there are no intermediate buffers involved, so as much data as is available can be decoded in one go. + When retrieving sample data, the returned data is in the standard Windows PCM format: 8-bit samples are unsigned, 16-bit samples are signed, 32-bit floating-point samples range from -1 to 1 (not clipped, so can actually be outside this range). That's unless the BASS_DATA_FLOAT flag is used, in which case, the sample data will be converted to 32-bit floating-point (if it isn't already). + This function is most useful if you wish to visualize (eg. spectrum analyze) the sound. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_ENDEDThe channel has reached the end. + BASS_ERROR_NOTAVAILThe BASS_DATA_AVAILABLE flag was used with a decoding channel. + BASS_ERROR_BUFLOSTShould not happen... check that a valid window handle was used with . + + + + + The following example assumes that you have created the stream with the BASS_DEFAULT flag. + So the buffer will contain 16-bit values...as an array of int - meaning one int (32bit) value will represent a stereo pair (left and right channel). + + int length = (int)Bass.BASS_ChannelSeconds2Bytes(channel, 0.03); // 30ms window + int[] data = new int[length/4]; // 2 x 16-bit and length in is bytes + length = Bass.BASS_ChannelGetData(channel, data, length); + // further processing of length/4 array elements...where each int value represents a stereo pair + // the HighWord contains the left channel + // the LowWord contains the right channel + + + Dim length As Integer = CInt(Bass.BASS_ChannelSeconds2Bytes(channel, 0.03)) + Dim data(length/4 - 1) As Integer ' 2 x 16-bit and length in is bytes + length = Bass.BASS_ChannelGetData(channel, data, length) + ' further processing of length/4 array elements...where each int value represents a stereo pair + ' the HighWord contains the left channel + ' the LowWord contains the right channel + + + + + + Retrieves the immediate sample data of a sample channel, stream, MOD music, or recording channel. + This overload uses a managed byte[] to reference the buffer data! + SHOULD ONLY BE USED, if the stream was created with BASS_SAMPLE_8BITS! + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM, or HRECORD. + The array (byte[]) to receive the data, e.g. when creating the channel with BASS_SAMPLE_8BITS! + Number of bytes wanted, and/or the following flags (): + + BASS_DATA_AVAILABLEQuery the amount of data the channel has buffered. This flag is primarily of use when recording, and can't be used with decoding channels as they do not have playback buffers. buffer can be when using this flag. + + + If an error occurs, -1 is returned, use to get the error code. + When requesting sample data, the number of bytes written to buffer will be returned (not necessarily the same as the number of bytes read when using the BASS_DATA_FLOAT flag). + When using the BASS_DATA_AVAILABLE flag, the number of bytes in the channel's buffer is returned. + + + This function can only return as much data as has been written to the channel's buffer, so it may not always be possible to get the amount of data requested, especially if you request large amounts. If you really do need large amounts, then increase the buffer lengths (BASS_CONFIG_BUFFER). + The BASS_DATA_AVAILABLE flag can be used to check how much data a channel's buffer contains at any time, including when stopped or stalled. + When requesting data from a "decoding channel" (BASS_STREAM_DECODE or BASS_MUSIC_DECODE was used at creation), there are no intermediate buffers involved, so as much data as is available can be decoded in one go. + When retrieving sample data, the returned data is in the standard Windows PCM format: 8-bit samples are unsigned, 16-bit samples are signed, 32-bit floating-point samples range from -1 to 1 (not clipped, so can actually be outside this range). That's unless the BASS_DATA_FLOAT flag is used, in which case, the sample data will be converted to 32-bit floating-point (if it isn't already). + This function is most useful if you wish to visualize (eg. spectrum analyze) the sound. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_ENDEDThe channel has reached the end. + BASS_ERROR_NOTAVAILThe BASS_DATA_AVAILABLE flag was used with a decoding channel. + BASS_ERROR_BUFLOSTShould not happen... check that a valid window handle was used with . + + + + + The following example assumes that you have created the stream with the BASS_SAMPLE_8BITS flag. + So the buffer will contain 8-bit values...as an array of byte. + + int length = (int)Bass.BASS_ChannelSeconds2Bytes(channel, 0.03); // 30ms window + byte[] data = new byte[length]; // 8-bit are bytes + length = Bass.BASS_ChannelGetData(channel, data, length); + + + Dim length As Integer = CInt(Bass.BASS_ChannelSeconds2Bytes(channel, 0.03)) + Dim data(length - 1) As Byte + length = Bass.BASS_ChannelGetData(channel, data, length) + + + + + + Translates a time (seconds) position into bytes, based on a channel's format. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM, or HRECORD. HSAMPLE handles may also be used. + The position to translate (in seconds, e.g. 0.03 = 30ms). + If successful, then the translated length in BYTES is returned, else -1 is returned. Use to get the error code. + + The translation is based on the channel's initial sample rate, when it was created. + The return value is rounded down to the position of the nearest sample. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + + + + Get the length of a 30ms window: + + int length = (int)Bass.BASS_ChannelSeconds2Bytes(channel, 0.03); + + + Dim length As Integer = CInt(Bass.BASS_ChannelSeconds2Bytes(channel, 0.03)) + + + + + + Translates a byte position into time (seconds), based on a channel's format. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM, or HRECORD. HSAMPLE handles may also be used. + The position in BYTES to translate. + If successful, then the translated length in seconds is returned, else a negative value is returned. Use to get the error code. + + The translation is based on the channel's initial sample rate, when it was created. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + + + + Getting the elapsed and remaining time: + + // length in bytes + long len = Bass.BASS_ChannelGetLength(channel); + // position in bytes + long pos = Bass.BASS_ChannelGetPosition(channel); + // the total time length + double totaltime = Bass.BASS_ChannelBytes2Seconds(channel, len); + // the elapsed time length + double elapsedtime = Bass.BASS_ChannelBytes2Seconds(channel, pos); + double remainingtime = totaltime - elapsedtime; + + + ' length in bytes + Dim len As Long = Bass.BASS_ChannelGetLength(channel) + ' position in bytes + Dim pos As Long = Bass.BASS_ChannelGetPosition(channel) + ' the total time length + Dim totaltime As Double = Bass.BASS_ChannelBytes2Seconds(channel, len) + ' the elapsed time length + Dim elapsedtime As Double = Bass.BASS_ChannelBytes2Seconds(channel, pos) + Dim remainingtime As Double = totaltime - elapsedtime + + + + + + Checks if a sample, stream, or MOD music is active (playing) or stalled. Can also check if a recording is in progress. + + The channel handle... a HCHANNEL / HMUSIC / HSTREAM / HRECORD handle. + The return value is one of the folowing (see ): + + BASS_ACTIVE_STOPPEDThe channel is not active, or handle is not a valid channel. + BASS_ACTIVE_PLAYINGThe channel is playing (or recording). + BASS_ACTIVE_PAUSEDThe channel is paused. + BASS_ACTIVE_STALLEDPlayback of the stream has been stalled due to there not being enough sample data to continue playing. The playback will automatically resume once there's sufficient data to do so. + + + + When using this function with a decoding channel, BASS_ACTIVE_PLAYING will be returned while there is still data to decode. + Once the end has been reached, BASS_ACTIVE_STOPPED will be returned. + BASS_ACTIVE_STALLED is never returned for decoding channels - you can tell a decoding channel is stalled if returns less data than requested, and this function still returns BASS_ACTIVE_PLAYING. + + + + BASSActive status = BASS_ChannelIsActive(stream); + if (status == BASSActive.BASS_ACTIVE_PLAYING) + { + // the stream is still playing + ... + } + + + Dim status As BASSActive = BASS_ChannelIsActive(stream) + If status = BASSActive.BASS_ACTIVE_PLAYING Then + ' the stream is still playing + ... + End If + + + + + + Locks a stream, MOD music or recording channel to the current thread. + + The channel handle... a HMUSIC, HSTREAM or HRECORD handle. + If , unlock the channel, else lock it. + If succesful, then is returned, else is returned. Use to get the error code. + + Locking a channel prevents other threads from performing most functions on it, including buffer updates. + Other threads wanting to access a locked channel will block until it is unlocked, so a channel should only be locked very briefly. + A channel must be unlocked in the same thread that it was locked. + + + Lock a channel to ensure that 2 DSP functions start together: + + Bass.BASS_ChannelLock(channel, true); // lock channel + Bass.BASS_ChannelSetDSP(channel, DspProc1, null, 0); // set 1st DSP + Bass.BASS_ChannelSetDSP(channel, DspProc2, null, 0); // set 2nd DSP + Bass.BASS_ChannelLock(channel, false); // unlock channel + + + Bass.BASS_ChannelLock(channel, True); // lock channel + Bass.BASS_ChannelSetDSP(channel, DspProc1, Nothing, 0); // set 1st DSP + Bass.BASS_ChannelSetDSP(channel, DspProc2, Nothing, 0); // set 2nd DSP + Bass.BASS_ChannelLock(channel, False); // unlock channel + + + + + + Retrieves the playback length of a channel. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM. HSAMPLE handles may also be used. + How to retrieve the length (one of the flags): + + BASS_POS_BYTESGet the length in bytes. + BASS_POS_MUSIC_ORDERSGet the length in orders. (HMUSIC only). + + Other modes may be supported by add-ons, see the documentation. + + If succesful, then the channel's length is returned, else -1 is returned. Use to get the error code. + + The exact length of a stream will be returned once the whole file has been streamed, until then it's not always possible to 100% accurately estimate the length of a stream. + The length is always exact for MP3/MP2/MP1 files when the BASS_STREAM_PRESCAN flag is used in the call. + Note: BASS_STREAM_PRESCAN is ONLY needed for files with a VBR, files with a CBR are always accurate. + + When the BASS_STREAM_PRESCAN flag is not used, the length is an (usually accurate) estimation based on the file size, until the whole file has been streamed (Note: This is ONLY needed for files with a VBR, files with a CBR are always accurate). + The length returned for OGG files will usually be exact (assuming the file is not corrupt), but for OGG files streamed from the internet (or "buffered" user file stream) it can be a very rough estimation until the whole file has been downloaded. + Retrieving the length of a MOD music requires that the BASS_MUSIC_PRESCAN flag was used in the call. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_NOTAVAILThe length is not available. + + + + + Get the duration (in seconds) of a channel: + + // length in bytes + long len = Bass.BASS_ChannelGetLength(channel, BASSMode.BASS_POS_BYTES); + // the time length + double time = Bass.BASS_ChannelBytes2Seconds(channel, len); + + + ' length in bytes + Dim len As Long = Bass.BASS_ChannelGetLength(channel, BASSMode.BASS_POS_BYTES) + ' the time length + Dim time As Double = Bass.BASS_ChannelBytes2Seconds(channel, len) + + + + + + Retrieves the playback length in bytes of a channel. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM. HSAMPLE handles may also be used. + If succesful, then the channel's length is returned, else -1 is returned. Use to get the error code. + + The exact length of a stream will be returned once the whole file has been streamed, until then it's not always possible to 100% accurately estimate the length of a stream. + The length is always exact for MP3/MP2/MP1 files when the BASS_STREAM_PRESCAN flag is used in the call. + Note: BASS_STREAM_PRESCAN is ONLY needed for files with a VBR, files with a CBR are always accurate. + + When the BASS_STREAM_PRESCAN flag is not used, the length is an (usually accurate) estimation based on the file size, until the whole file has been streamed (Note: This is ONLY needed for files with a VBR, files with a CBR are always accurate). + The length returned for OGG files will usually be exact (assuming the file is not corrupt), but for OGG files streamed from the internet (or "buffered" user file stream) it can be a very rough estimation until the whole file has been downloaded. + Retrieving the length of a MOD music requires that the BASS_MUSIC_PRESCAN flag was used in the call. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_NOTAVAILThe length is not available. + + + + + Get the duration (in seconds) of a channel: + + // length in bytes + long len = Bass.BASS_ChannelGetLength(channel); + // the time length + double time = Bass.BASS_ChannelBytes2Seconds(channel, len); + + + ' length in bytes + Dim len As Long = Bass.BASS_ChannelGetLength(channel) + ' the time length + Dim time As Double = Bass.BASS_ChannelBytes2Seconds(channel, len) + + + + + + Sets up a synchronizer on a MOD music, stream or recording channel. + + The channel handle... a HMUSIC, HSTREAM or HRECORD. + The type of sync (see the table below or ), you may also use these flags: + + BASS_SYNC_ONETIMECall the sync only once, and then remove it from the channel. + BASS_SYNC_MIXTIMECall the sync function when the sync occurs during decoding/mixing, instead of delaying the call until the sync is actually heard. This is automatically applied with decoding channels, as they can not be played/heard. + + + The sync parameters, depends on the sync type... see the table below. + The callback function which should be invoked with the sync. + User instance data to pass to the callback function. + If succesful, then the new synchronizer's handle is returned, else 0 is returned. Use to get the error code. + + Sync types, with param and data definitions: + + BASS_SYNC_DOWNLOADSync when downloading of an internet (or "buffered" user file) stream is done. + param : not used. + data : not used. + + BASS_SYNC_ENDSync when a channel reaches the end. Note that some MOD musics never reach the end, they may jump to another position first. If the BASS_MUSIC_STOPBACK flag is used with a MOD music (through or ), then this sync will also be called when a backward jump effect is played. + param : not used. + data : 1 = the sync is triggered by a backward jump in a MOD music, otherwise not used + + BASS_SYNC_FREESync when a channel is freed. This can be useful when you need to release some resources associated with the channel. Note that you will not be able to use any BASS functions with the channel in the callback (the channel will no longer exist). + param : not used. + data : not used. + + BASS_SYNC_METASync when metadata is received in a Shoutcast stream. This sync is also triggered when a new logical-bitstream begins in a chained OGG stream (multiple streams are strung one-after-another), in which case the metadata is the updated OGG tags. (see example below) + param : not used. + data : not used - the updated metadata is available from (BASS_TAG_META) + + BASS_SYNC_MUSICFXSync when the sync effect is used in a MOD music. The sync effect is E8x or Wxx for the XM/MTM/MOD formats, and S2x for the IT/S3M formats (where x = any value). + param : 0 = the position is passed to the callback (data : LOWORD = order, HIWORD = row), + param : 1 = the value of x is passed to the callback (data : x value). + + BASS_SYNC_MUSICINSTSync when an instrument (sample for the MOD/S3M/MTM formats) is played in a MOD music (not including retrigs). + param : LOWORD = instrument (1=first), HIWORD = note (0=c0...119=b9, -1=all). + data : LOWORD = note, HIWORD = volume (0-64). + + BASS_SYNC_MUSICPOSSync when a MOD music reaches an order:row position. + param : LOWORD = order (0=first, -1=all), HIWORD = row (0=first, -1=all). + data : LOWORD = order, HIWORD = row. + + BASS_SYNC_OGG_CHANGESync when a new logical bitstream begins in a chained OGG stream. Updated tags are available from . + param : not used. + data : not used. + + BASS_SYNC_POSSync when a channel reaches a position. + param : position in bytes (automatically rounded down to nearest sample). + data : not used. + + BASS_SYNC_SETPOSSync when a channel's position is set, including when looping/restarting. + param : not used. + data : 0 = playback buffer is not flushed, 1 = playback buffer is flushed. + + BASS_SYNC_SLIDESync when an attribute slide has completed. + param : not used. + data : the type of slide completed (one of the BASS_SLIDE_xxx values). + + BASS_SYNC_STALLSync when playback of the channel is stalled/resumed. + param : not used. + data : 0 = stalled, 1 = resumed. + + + Other sync types may be supported by add-ons, see the documentation. + + Multiple synchronizers may be used per channel, and they can be set before and while playing. Equally, synchronizers can also be removed at any time, using . If the BASS_SYNC_ONETIME flag is used, then the sync is automatically removed after its first occurrence. + The BASS_SYNC_MIXTIME flag can be used with BASS_SYNC_END or BASS_SYNC_POS/MUSICPOS syncs to implement custom looping, by using in the callback. + A MIXTIME sync can also be used to add or remove DSP/FX at specific points, or change a HMUSIC channel's flags or attributes (see ). + The BASS_SYNC_MIXTIME flag can also be useful with a BASS_SYNC_SETPOS sync, to reset DSP states after seeking. + Several of the sync types are triggered in the process of rendering the channel's sample data; for example, BASS_SYNC_POS and BASS_SYNC_END syncs, when the rendering reaches the sync position or the end, respectively. Those sync types should be set before starting playback or pre-buffering (ie. before any rendering), to avoid missing any early sync events. + With recording channels, BASS_SYNC_POS syncs are triggered just before the receives the block of data containing the sync position. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_ILLTYPEAn illegal was specified. + BASS_ERROR_ILLPARAMAn illegal was specified. + + + + + Set a sync to get notified when the channel reaches the end: + + private SYNCPROC _mySync; + ... + _mySync = new SYNCPROC(EndSync); + Bass.BASS_ChannelSetSync(_stream, BASSSync.BASS_SYNC_END | BASSSync.BASS_SYNC_MIXTIME, + 0, _mySync, IntPtr.Zero); + ... + private void EndSync(int handle, int channel, int data, IntPtr user) + { + // the 'channel' has ended - jump to the beginning + Bass.BASS_ChannelSetPosition(channel, 0L); + } + + + Private _mySync As SYNCPROC + ... + _mySync = New SYNCPROC(AddressOf EndSync) + Bass.BASS_ChannelSetSync(_stream, BASSSync.BASS_SYNC_END Or BASSSync.BASS_SYNC_MIXTIME, + 0, _mySync, IntPtr.Zero) + ... + Private Sub EndSync(ByVal handle As Integer, ByVal channel As Integer, + ByVal data As Integer, ByVal user As IntPtr) + ' the 'channel' has ended - jump to the beginning + Bass.BASS_ChannelSetPosition(channel, 0L) + End Sub + + Process metadata received from an internet stream: + + private SYNCPROC _mySync; + ... + int stream = Bass.BASS_StreamCreateURL(url, 0, BASSFlag.BASS_DEFAULT, null, 0); + // set a sync to get notified on stream title updates + _mySync = new SYNCPROC(MetaSync); + Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_META, 0, _mySync, IntPtr.Zero); + Bass.BASS_ChannelPlay(stream, false); + ... + private void MetaSync(int handle, int channel, int data, IntPtr user) + { + // BASS_SYNC_META is triggered + string[] tags = Bass.BASS_ChannelGetTagsMETA(channel); + foreach (string tag in tags) + Console.WriteLine(tag); + } + + + Private _mySync As SYNCPROC + ... + Dim stream As Integer = Bass.BASS_StreamCreateURL(url, 0, BASSFlag.BASS_DEFAULT, Nothing, 0) + ' set a sync to get notified on stream title updates + _mySync = New SYNCPROC(AddressOf MetaSync) + Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_META, 0, _mySync, IntPtr.Zero) + Bass.BASS_ChannelPlay(stream, False) + ... + Private Sub MetaSync(ByVal handle As Integer, ByVal channel As Integer, + ByVal data As Integer, ByVal user As IntPtr) + ' BASS_SYNC_META is triggered + Dim tags() As String = Bass.BASS_ChannelGetTagsMETA(channel) + Dim tag As String + For Each tag In tags + Console.WriteLine(tag) + End Sub + + + + + + Sets an effect on a stream, MOD music, or recording channel. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + One of the following types of effect (see ): + + BASS_FX_DX8_CHORUSDX8 Chorus. Use structure to set/get parameters. + BASS_FX_DX8_COMPRESSORDX8 Compression. Use structure to set/get parameters. + BASS_FX_DX8_DISTORTIONDX8 Distortion. Use structure to set/get parameters. + BASS_FX_DX8_ECHODX8 Echo. Use structure to set/get parameters. + BASS_FX_DX8_FLANGERDX8 Flanger. Use structure to set/get parameters. + BASS_FX_DX8_GARGLEDX8 Gargle. Use structure to set/get parameters. + BASS_FX_DX8_I3DL2REVERBDX8 I3DL2 (Interactive 3D Audio Level 2) reverb. Use structure to set/get parameters. + BASS_FX_DX8_PARAMEQDX8 Parametric equalizer. Use structure to set/get parameters. + BASS_FX_DX8_REVERBDX8 Reverb. Use structure to set/get parameters. + + Other effects may be supported by add-ons, e.g. BASS_FX: + + BASS_FX_BFX_MIXBASS_FX Channel Swap/Remap/Downmix. Use structure to set/get parameters. + BASS_FX_BFX_ROTATEBASS_FX Channel Rotate. No parameters. + BASS_FX_BFX_ECHOBASS_FX Echo. Use structure to set/get parameters. + BASS_FX_BFX_FLANGERBASS_FX Flanger. Use structure to set/get parameters. + BASS_FX_BFX_VOLUMEBASS_FX Volume. Use structure to set/get parameters. + BASS_FX_BFX_PEAKEQBASS_FX Peaking Equalizer. Use structure to set/get parameters. + BASS_FX_BFX_REVERBBASS_FX Reverb. Use structure to set/get parameters. + BASS_FX_BFX_LPFBASS_FX Low Pass Filter. Use structure to set/get parameters. + BASS_FX_BFX_DAMPBASS_FX Dynamic Amplification. Use structure to set/get parameters. + BASS_FX_BFX_AUTOWAHBASS_FX Auto Wah. Use structure to set/get parameters. + BASS_FX_BFX_ECHO2BASS_FX Echo 2. Use structure to set/get parameters. + BASS_FX_BFX_PHASERBASS_FX Phaser. Use structure to set/get parameters. + BASS_FX_BFX_ECHO3BASS_FX Echo 3. Use structure to set/get parameters. + BASS_FX_BFX_CHORUSBASS_FX Chorus. Use structure to set/get parameters. + BASS_FX_BFX_APFBASS_FX All Pass Filter. Use structure to set/get parameters. + BASS_FX_BFX_COMPRESSORBASS_FX Compressor. Use structure to set/get parameters. + BASS_FX_BFX_DISTORTIONBASS_FX Distortion. Use structure to set/get parameters. + BASS_FX_BFX_COMPRESSOR2BASS_FX Compressor. Use structure to set/get parameters. + + + The priority of the new FX, which determines it's position in the DSP chain - DSP/FX with higher priority are applied before those with lower. This parameter has no effect with DX8 effects when the "with FX flag" DX8 effect implementation is used. + If succesful, then the new effect's handle is returned, else 0 is returned. Use to get the error code. + + Multiple effects may be used per channel. Use to remove an effect. Use to set an effect's parameters. + Effects can be applied to MOD musics and streams, but not samples. If you want to apply an effect to a sample, you could use a stream instead. + Depending on the DX8 effect implementation being used by the channel, the channel may have to be stopped before adding or removing DX8 effects on it. + If necessary, that is done automatically and the channel is resumed afterwards. + Platform-specific + DX8 effects are a Windows feature requiring DirectX 8, or DirectX 9 for floating-point support. On other platforms, they are emulated by BASS, except for the following which are currently unsupported: COMPRESSOR, GARGLE, and I3DL2REVERB. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_ILLTYPEAn illegal was specified. + BASS_ERROR_NOFXDX8 effects are unavailable. + BASS_ERROR_FORMATThe channel's format is not supported by the effect. It may be floating-point (without DX9) or more than stereo. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + DX8 effects are a Windows feature requiring DirectX 8, or DirectX 9 for floating-point support. On other platforms, they are emulated by BASS, except for the following which are currently unsupported: COMPRESSOR, GARGLE, and I3DL2REVERB. On Windows CE, only PARAMEQ is supported. + + + + BASS_DX8_ECHO echo = new BASS_DX8_ECHO(90f, 50f, 500f, 500f, true); + int channel = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_DEFAULT); + int fxEchoHandle = Bass.BASS_ChannelSetFX(channel, BASSFXType.BASS_FX_ECHO, 1); + ... + // changing the echo effect, dry/wet mix... + echo.fWetDryMix = 50f; + Bass.BASS_FXSetParameters(fxEchoHandle, echo); + + + Dim echo As New BASS_DX8_ECHO(90F, 50F, 500F, 500F, True) + Dim channel As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_DEFAULT) + Dim fxEchoHandle As Integer = Bass.BASS_ChannelSetFX(channel, BASSFXType.BASS_FX_ECHO, 1) + ... + ' changing the echo effect, dry/wet mix... + echo.fWetDryMix = 50F + Bass.BASS_FXSetParameters(fxEchoHandle, echo) + + + + + + Retrieves the device that the channel is using. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM, or HRECORD. HSAMPLE handles may also be used. + If successful, the device number is returned, else -1 is returned. Use to get the error code. + Recording devices are indicated by the HIWORD of the return value being 1, when this function is called with a HRECORD channel. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + + + + Check, if a device number is a recording device: + + bool isRecordingDevice = false; + int device = Bass.BASS_ChannelGetDevice(stream); + if (device != -1 && Utils.HighWord(device) == 1) + isRecordingDevice = true; + + + Dim isRecordingDevice As Boolean = False + Dim device As Integer = Bass.BASS_ChannelGetDevice(stream) + If device <> - 1 AndAlso Utils.HighWord(device) = 1 Then + isRecordingDevice = True + End If + + + + + + Changes the device that a stream, MOD music or sample is using. + + The channel or sample handle... only HMUSIC, HSTREAM or HSAMPLE are supported. + The device to use...0 = no sound, 1 = first real output device. + If succesful, then is returned, else is returned. Use to get the error code. + All of the channel's current settings are carried over to the new device, but if the channel is using the "with FX flag" DX8 effect implementation, + the internal state (eg. buffers) of the DX8 effects will be reset. Using the "without FX flag" DX8 effect implementation, the state of the DX8 effects is preserved. + When changing a sample's device, all the sample's existing channels (HCHANNELs) are freed. It's not possible to change the device of an individual sample channel. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_DEVICE is invalid. + BASS_ERROR_INITThe requested device has not been initialized. + BASS_ERROR_ALREADYThe channel is already using the requested device. + BASS_ERROR_NOTAVAILOnly decoding channels are allowed to use the "no sound" device. + BASS_ERROR_FORMATThe sample format is not supported by the device/drivers. If the channel is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported. + BASS_ERROR_MEMThere is insufficient memory. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + // init device 1 and 2 + Bass.BASS_Init(1, 44100, BASSInit.BASS_DEVICE_DEFAULT, this.Handle); + // now device 1 is the current one + Bass.BASS_Init(2, 44100, BASSInit.BASS_DEVICE_DEFAULT, this.Handle); + // now device 2 is the current one + ... + // create the stream on device 1 + Bass.BASS_SetDevice(1); + // now device 1 is the current one + int stream = Bass.BASS_StreamCreateFile("afile.mp3", 0, 0, BASSFlag.BASS_DEFAULT); + Bass.BASS_ChannelPlay(stream, false); + ... + // move the channel to device 2 + Bass.BASS_ChannelSetDevice(stream, 2); + + + ' init device 1 and 2 + Bass.BASS_Init(1, 44100, BASSInit.BASS_DEVICE_DEFAULT, Me.Handle) + ' now device 1 is the current one + Bass.BASS_Init(2, 44100, BASSInit.BASS_DEVICE_DEFAULT, Me.Handle) + ' now device 2 is the current one + ' create the stream on device 1 + Bass.BASS_SetDevice(1) + ' now device 1 is the current one + Dim stream As Integer = Bass.BASS_StreamCreateFile("afile.mp3", 0, 0, BASSFlag.BASS_DEFAULT) + Bass.BASS_ChannelPlay(stream, False) + ... + ' move the channel to device 2 + Bass.BASS_ChannelSetDevice(stream, 2) + + + + + + Stops a sample, stream, MOD music, or recording. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM or HRECORD handle. + If successful, is returned, else is returned. Use to get the error code. + + Stopping a user stream (created with ) will clear its buffer contents, and stopping a sample channel (HCHANNEL) will result in it being freed. + Use instead if you wish to stop a user stream and then resume it from the same point. + When used with a "decoding channel" (BASS_STREAM_DECODE or BASS_MUSIC_DECODE was used at creation), this function will end the channel at its current position, + so that it's not possible to decode any more data from it. Any BASS_SYNC_END syncs that have been set on the channel will not be triggered by this, they are only triggered when reaching the natural end. + can be used to reset the channel and start decoding again. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + + + + + + + Pauses a sample, stream, MOD music, or recording. + + The channel handle... a HCHANNEL / HMUSIC / HSTREAM / HRECORD handle. + If successful, is returned, else is returned. Use to get the error code. + Use to resume a paused channel. can be used to stop a paused channel. + + + ERROR CODEDescription + BASS_ERROR_NOPLAYThe channel is not playing (or is not a valid channel). + BASS_ERROR_DECODEThe channel is not playable, it's a "decoding channel". + BASS_ERROR_ALREADYThe channel is already paused. + + + + + + + Sets the value of an attribute of a sample, stream or MOD music. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM or HRECORD. + The attribute to set the value of (one of the following, see ): + + BASS_ATTRIB_FREQThe sample rate, 100 (min) to 100000 (max), 0 = original rate (when the channel was created). + BASS_ATTRIB_PANThe panning/balance position, -1 (full left) to +1 (full right), 0 = centre. + BASS_ATTRIB_VOLThe volume level, 0 (silent) to 1 (full). + BASS_ATTRIB_SRCSample rate conversion quality. + BASS_ATTRIB_EAXMIXEAX wet/dry mix, 0 (full dry) to 1 (full wet), -1 = automatically calculate the mix based on the distance (the default). + BASS_ATTRIB_MUSIC_AMPLIFYThe amplification level, 0 (min) to 100 (max) rounded down to a whole number. (HMUSIC) + BASS_ATTRIB_MUSIC_BPMThe BPM, 1 (min) to 255 (max) rounded down to a whole number. (HMUSIC) + BASS_ATTRIB_MUSIC_PANSEPThe Pan separation level, 0 (min) to 100 (max), 50 = linear rounded down to a whole number. (HMUSIC) + BASS_ATTRIB_MUSIC_PSCALERThe Position scaler, 1 (min) to 256 (max) rounded down to a whole number. (HMUSIC) + BASS_ATTRIB_MUSIC_SPEEDThe Speed, 0 (min) to 255 (max) rounded down to a whole number. (HMUSIC) + BASS_ATTRIB_MUSIC_VOL_CHANA channel volume level, 0 (silent) to 1 (full). (HMUSIC) + BASS_ATTRIB_MUSIC_VOL_GLOBALGlobal volume level. (HMUSIC) + BASS_ATTRIB_MUSIC_VOL_INSTAn instrument/sample volume level, 0 (min) to 64 (max, 128 for IT format) rounded down to a whole number. (HMUSIC) + + Other attributes may be supported by add-ons, e.g. BASS_FX: + + BASS_ATTRIB_TEMPOThe tempo of a channel, [-95%...0...+5000%] percents. + BASS_ATTRIB_TEMPO_PITCHThe pitch of a channel, [-60...0...+60] semitones. + BASS_ATTRIB_TEMPO_FREQThe sample rate of a channel in Hz, but calculates by the same % as BASS_ATTRIB_TEMPO. + BASS_ATTRIB_TEMPO_OPTION_USE_AA_FILTERUse the AA Filter for a tempo channel (=1, =0). + BASS_ATTRIB_TEMPO_OPTION_AA_FILTER_LENGTHSets the AA Filter length in taps (between 8 and 128). + BASS_ATTRIB_TEMPO_OPTION_USE_QUICKALGOUse the tempo quick algorithm for a tempo channel (=1, =0). + BASS_ATTRIB_TEMPO_OPTION_SEQUENCE_MSSets the tempo sequence in ms. of a tempo channel (default = 82). + BASS_ATTRIB_TEMPO_OPTION_SEEKWINDOW_MSSets the tempo seek window in ms. of a tempo channel (default = 82). + BASS_ATTRIB_TEMPO_OPTION_OVERLAP_MSSets the tempo overlap in ms. of a tempo channel (default = 12). + BASS_ATTRIB_REVERSE_DIRSets the playback direction of a reverse channel (-1=reverse, 1=forward, or use one of the flags). + + + The new attribute value. See the attribute's documentation for details on the possible values. + If successful, is returned, else is returned. Use to get the error code. + + The actual attribute value may not be exactly the same as requested, due to precision differences. For example, an attribute might only allow whole number values. can be used to confirm what the value is. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_ILLTYPE is not valid. + BASS_ERROR_ILLPARAM is not valid. See the attribute's documentation for the valid range of values. + + Some attributes may have additional error codes, see the documentation + + + Change the volume of a channel to 50%: + + int stream = Bass.BASS_StreamCreateFile("afile.mp3", 0, 0, BASSFlag.BASS_DEFAULT); + Bass.BASS_ChannelPlay(stream, false); + ... + Bass.BASS_ChannelSetAttribute(stream, BASSAttribute.BASS_ATTRIB_VOL, 0.5f); + + + Dim stream As Integer = Bass.BASS_StreamCreateFile("afile.mp3", 0, 0, BASSFlag.BASS_DEFAULT) + Bass.BASS_ChannelPlay(stream, False) + ... + Bass.BASS_ChannelSetAttribute(stream, BASSAttribute.BASS_ATTRIB_VOL, 0.5F) + + + + + + Retrieves the value of an attribute of a sample, stream or MOD music. Can also get the sample rate of a recording channel. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM or HRECORD. + The attribute to set the value of (one of the following, see ): + + BASS_ATTRIB_EAXMIXEAX wet/dry mix. + BASS_ATTRIB_CPUCPU usage. (HMUSIC/HSTREAM) + BASS_ATTRIB_FREQSample rate. + BASS_ATTRIB_MUSIC_AMPLIFYAmplification level. (HMUSIC) + BASS_ATTRIB_MUSIC_BPMBPM. (HMUSIC) + BASS_ATTRIB_MUSIC_PANSEPPan separation level. (HMUSIC) + BASS_ATTRIB_MUSIC_PSCALERPosition scaler. (HMUSIC) + BASS_ATTRIB_MUSIC_SPEEDSpeed. (HMUSIC) + BASS_ATTRIB_MUSIC_VOL_CHANA channel volume level. (HMUSIC) + BASS_ATTRIB_MUSIC_VOL_GLOBALGlobal volume level. (HMUSIC) + BASS_ATTRIB_MUSIC_VOL_INSTAn instrument/sample volume level. (HMUSIC) + BASS_ATTRIB_NOBUFFERNon-Windows only: Playback buffering switch. (HMUSIC/HSTREAM) + BASS_ATTRIB_PANPanning/balance position. + BASS_ATTRIB_SRCSample rate conversion quality. + BASS_ATTRIB_VOLVolume level. + + Other attributes may be supported by add-ons, e.g. BASS_FX: + + BASS_ATTRIB_TEMPOThe tempo of a channel in percent. + BASS_ATTRIB_TEMPO_PITCHThe pitch of a channel in semitones. + BASS_ATTRIB_TEMPO_FREQThe sample rate of a channel in Hz. + BASS_ATTRIB_TEMPO_OPTION_USE_AA_FILTERAA Filter used on a tempo channel. + BASS_ATTRIB_TEMPO_OPTION_AA_FILTER_LENGTHThe AA Filter length in taps. + BASS_ATTRIB_TEMPO_OPTION_USE_QUICKALGOTempo quick algorithm used on a tempo channel. + BASS_ATTRIB_TEMPO_OPTION_SEQUENCE_MSThe tempo sequence in ms. used on a tempo channel. + BASS_ATTRIB_TEMPO_OPTION_SEEKWINDOW_MSThe tempo seek window in ms. used on a tempo channel. + BASS_ATTRIB_TEMPO_OPTION_OVERLAP_MSThe tempo overlap in ms. used on a tempo channel. + BASS_ATTRIB_REVERSE_DIRThe current playback direction of a reverse stream. + + + Pointer to a variable to receive the attribute value. + If successful, is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_ILLTYPE is not valid. + + Some attributes may have additional error codes, see the documentation + + + Get the current volume of a channel: + + float vol = 0f; + if (Bass.BASS_ChannelGetAttribute(stream, BASSAttribute.BASS_ATTRIB_VOL, ref vol)) + Console.WriteLine("Volume={0}", vol); + + + Dim vol As Single = 0F + If Bass.BASS_ChannelGetAttribute(stream, BASSAttribute.BASS_ATTRIB_VOL, vol) Then + Console.WriteLine("Volume={0}", vol) + End If + + + + + + Modifies and retrieves a channel's flags. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM. + A combination of these flags (see ): + + BASS_SAMPLE_LOOPLoop the channel. + BASS_STREAM_AUTOFREEAutomatically free the channel when playback ends. Note that the BASS_MUSIC_AUTOFREE flag is identical to this flag. (HSTREAM/HMUSIC) + BASS_STREAM_RESTRATERestrict the download rate. (HSTREAM) + BASS_MUSIC_RAMPUse "normal" ramping. (HMUSIC) + BASS_MUSIC_RAMPSUse "sensitive" ramping. (HMUSIC) + BASS_MUSIC_SURROUNDUse surround sound. (HMUSIC) + BASS_MUSIC_SURROUND2Use surround sound mode 2. (HMUSIC) + BASS_MUSIC_NONINTERUse non-interpolated mixing. (HMUSIC) + BASS_MUSIC_SINCINTERUse sinc interpolated sample mixing. (HMUSIC) + BASS_MUSIC_FT2MODUse FastTracker 2 .MOD playback. (HMUSIC) + BASS_MUSIC_PT1MODUse ProTracker 1 .MOD playback. (HMUSIC) + BASS_MUSIC_POSRESETStop all notes when seeking. (HMUSIC) + BASS_MUSIC_POSRESETEXStop all notes and reset BPM/etc when seeking. (HMUSIC) + BASS_MUSIC_STOPBACKStop when a backward jump effect is played. (HMUSIC) + BASS_SPEAKER_xxxSpeaker assignment flags. (HSTREAM/HMUSIC) + + Other attributes may be supported by add-ons, see the documentation + + The flags (as above) to modify. Flags that are not included in this are left as they are, so it can be set to 0 in order to just retrieve the current flags. To modify the speaker flags, any of the BASS_SPEAKER_xxx flags can be used in the mask (no need to include all of them). + If successful, the channel's updated flags are returned, else -1 is returned. Use to get the error code. + + Some flags may not be adjustable in some circumstances, so the return value should be checked to confirm any changes. + The flags listed above are just the flags that can be modified, and there may be additional flags present in the return value. + See the documentation for a full list of flags. + Streams that are created by add-ons may have additional flags available. There is a limited number of possible flag values though, so some add-ons may use the same flag value for different things. + This means that when using add-on specific flags with a stream created via the plugin system, it is a good idea to first confirm that the add-on is handling the stream, by checking its ctype via . + During playback, the effects of flag changes are not heard instantaneously, due to buffering. To reduce the delay, use the config option to reduce the buffer length. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + + + + + Toggle looping on a channel: + + if ((Bass.BASS_ChannelFlags(channel, BASSFlag.BASS_DEFAULT, BASSFlag.BASS_DEFAULT) & BASSFlag.BASS_SAMPLE_LOOP) == BASSFlag.BASS_SAMPLE_LOOP) + { + // loop flag was set, so remove it + Bass.BASS_ChannelFlags(channel, BASSFlag.BASS_DEFAULT, BASSFlag.BASS_SAMPLE_LOOP); + } + else + { + // loop flag was not set, so set it + Bass.BASS_ChannelFlags(channel, BASSFlag.BASS_SAMPLE_LOOP, BASSFlag.BASS_SAMPLE_LOOP); + } + + + If (Bass.BASS_ChannelFlags(channel, BASSFlag.BASS_DEFAULT, BASSFlag.BASS_DEFAULT) And BASSFlag.BASS_SAMPLE_LOOP) = BASSFlag.BASS_SAMPLE_LOOP Then + ' loop flag was set, so remove it + Bass.BASS_ChannelFlags(channel, BASSFlag.BASS_DEFAULT, BASSFlag.BASS_SAMPLE_LOOP) + Else + ' loop flag was not set, so set it + Bass.BASS_ChannelFlags(channel, BASSFlag.BASS_SAMPLE_LOOP, BASSFlag.BASS_SAMPLE_LOOP) + End If + + + + + + Updates the playback buffer of a stream or MOD music. + + The channel handle... a HMUSIC or HSTREAM. + The amount to render, in milliseconds... 0 = default (2 x ). This is capped at the space available in the buffer. + If successful, is returned, else is returned. Use to get the error code. + + When starting playback of a stream or MOD music, after creating it or changing its position, there will be a slight delay while the initial data is decoded for playback. + Usually the delay is not noticeable or important, but if you need playback to start instantly when you call , then use this function first. + The length parameter should be at least equal to the . + It may not always be possible to render the requested amount of data, in which case this function will still succeed. + (BASS_DATA_AVAILABLE) can be used to check how much data a channel has buffered for playback. + When automatic updating is disabled ( = 0 or = 0), this function could be used instead of to implement different update periods for different channels, + instead of a single update period for all. Unlike , this function can also be used while automatic updating is enabled. + The CPU usage of this function is not included in the reading. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_NOTAVAILDecoding channels do not have playback buffers. + BASS_ERROR_ENDEDThe channel has ended. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + Pre-buffer to enable instant playback: + + int stream = Bass.BASS_StreamCreateFile("afile.mp3", 0, 0, BASSFlag.BASS_STREAM_PRESCAN); + // pre-buffer + Bass.BASS_ChannelUpdate(stream, 0); + // start playback + Bass.BASS_ChannelPlay(stream, false); + + + Dim stream As Integer = Bass.BASS_StreamCreateFile("afile.mp3", 0, 0, BASSFlag.BASS_STREAM_PRESCAN) + ' pre-buffer + Bass.BASS_ChannelUpdate(stream, 0) + ' start playback + Bass.BASS_ChannelPlay(stream, False) + + + + + + Checks if an attribute (or any attribute) of a sample, stream, or MOD music is sliding. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM or HRECORD. + The attribute to check for sliding (one of the following, see or 0 for any attribute): + + BASS_ATTRIB_EAXMIXEAX wet/dry mix. + BASS_ATTRIB_FREQSample rate. + BASS_ATTRIB_PANPanning/balance position. + BASS_ATTRIB_VOLVolume level. + BASS_ATTRIB_MUSIC_AMPLIFYAmplification level. (HMUSIC) + BASS_ATTRIB_MUSIC_BPMBPM. (HMUSIC) + BASS_ATTRIB_MUSIC_PANSEPPan separation level. (HMUSIC) + BASS_ATTRIB_MUSIC_PSCALERPosition scaler. (HMUSIC) + BASS_ATTRIB_MUSIC_SPEEDSpeed. (HMUSIC) + BASS_ATTRIB_MUSIC_VOL_CHANA channel volume level. (HMUSIC) + BASS_ATTRIB_MUSIC_VOL_GLOBALGlobal volume level. (HMUSIC) + BASS_ATTRIB_MUSIC_VOL_INSTAn instrument/sample volume level. (HMUSIC) + + Other attributes may be supported by add-ons, see the documentation + + If the attribute (or any) is sliding, then is returned, else is returned. + + Wait until a volume slideing has finished: + + while (Bass.BASS_ChannelIsSliding(channel, BASSAttribute.BASS_ATTRIB_VOL)) + { + Thread.Sleep(20); // wait 20ms + } + + + While Bass.BASS_ChannelIsSliding(channel, BASSAttribute.BASS_ATTRIB_VOL) + Thread.Sleep(20) ' wait 20ms + End While + + + + + + Slides a channel's attribute from its current value to a new value. + + The channel handle... a HCHANNEL, HSTREAM or HMUSIC, or HRECORD. + The attribute to slide the value of (one of the following, see ): + + BASS_ATTRIB_FREQSample rate. + BASS_ATTRIB_PANPanning/balance position. + BASS_ATTRIB_VOLVolume level. + BASS_ATTRIB_EAXMIXEAX wet/dry mix. + BASS_ATTRIB_MUSIC_AMPLIFYAmplification level. (HMUSIC) + BASS_ATTRIB_MUSIC_BPMBPM. (HMUSIC) + BASS_ATTRIB_MUSIC_PANSEPPan separation level. (HMUSIC) + BASS_ATTRIB_MUSIC_PSCALERPosition scaler. (HMUSIC) + BASS_ATTRIB_MUSIC_SPEEDSpeed. (HMUSIC) + BASS_ATTRIB_MUSIC_VOL_CHANA channel volume level. (HMUSIC) + BASS_ATTRIB_MUSIC_VOL_GLOBALGlobal volume level. (HMUSIC) + BASS_ATTRIB_MUSIC_VOL_INSTAn instrument/sample volume level. (HMUSIC) + + Other attributes may be supported by add-ons, see the documentation + + The new attribute value. See the attribute's documentation for details on the possible values. + The length of time (in milliseconds) that it should take for the attribute to reach the . + If successful, then is returned, else is returned. Use to get the error code. + + This function is similar to , except that the attribute is ramped to the value over the specified period of time. + Another difference is that the value is not pre-checked. If it is invalid, the slide will simply end early. + If an attribute is already sliding, then the old slide is stopped and replaced by the new one. + can be used to check if an attribute is currently sliding. A BASS_SYNC_SLIDE sync can also be set via , to be triggered at the end of a slide. + The sync will not be triggered in the case of an existing slide being replaced by a new one. + Attribute slides are unaffected by whether the channel is playing, paused or stopped. They carry on regardless. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_ILLTYPE is not valid. + + Some attributes may have additional error codes, see the documentation. + + + + Fadeout a channel's volume over a period of 1 second: + + Bass.BASS_ChannelSlideAttribute(channel, BASSAttribute.BASS_ATTRIB_VOL, 0f, 1000); + + + Bass.BASS_ChannelSlideAttribute(channel, BASSAttribute.BASS_ATTRIB_VOL, 0F, 1000) + + + + + + Sets the 3D attributes of a sample, stream, or MOD music channel with 3D functionality. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM. + The 3D processing mode... one of these flags, -1 = leave current (see ): + + BASS_3DMODE_NORMALNormal 3D processing. + BASS_3DMODE_RELATIVEThe channel's 3D position (position/velocity/orientation) is relative to the listener. When the listener's position/velocity/orientation is changed with , the channel's position relative to the listener does not change. + BASS_3DMODE_OFFTurn off 3D processing on the channel, the sound will be played in the centre. + + + The minimum distance. The channel's volume is at maximum when the listener is within this distance... less than 0.0 = leave current. + The maximum distance. The channel's volume stops decreasing when the listener is beyond this distance... less than 0.0 = leave current. + The angle of the inside projection cone in degrees... 0 (no cone) - 360 (sphere), -1 = leave current. + The angle of the outside projection cone in degrees... 0 (no cone) - 360 (sphere), -1 = leave current. + The delta-volume outside the outer projection cone... 0 (silent) - 100 (same as inside the cone), -1 = leave current. + If succesful, then is returned, else is returned. Use to get the error code. + + The iangle and oangle parameters must both be set in a single call to this function (ie. you can't set one without the other). + The iangle and oangle angles decide how wide the sound is projected around the orientation angle. Within the inside angle the volume level is the channel volume, as set with . + Outside the outer angle, the volume changes according to the outvol value. Between the inner and outer angles, the volume gradually changes between the inner and outer volume levels. + If the inner and outer angles are 360 degrees, then the sound is transmitted equally in all directions. + As with all 3D functions, use to apply the changes made. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_NO3DThe channel does not have 3D functionality. + BASS_ERROR_ILLPARAMOne or more of the attribute values is invalid. + + + + + + + Retrieves the 3D attributes of a sample, stream, or MOD music channel with 3D functionality. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM. + The 3D processing mode (see ). + The minimum distance. + The maximum distance. + The angle of the inside projection cone. + The angle of the outside projection cone. + The delta-volume outside the outer projection cone. + If succesful, then is returned, else is returned. Use to get the error code. + The iangle and oangle parameters must both be retrieved in a single call to this function (ie. you can't retrieve one without the other). See for an explanation of the parameters. + This overload uses reference types, so you need to specify all parameters here and therefore can only get the parameters all together. See the other overloads which allows you to retrieve only certain values. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_NO3DThe channel does not have 3D functionality. + + + + + + BASS3DMode mode = BASS3DMode.BASS_3DMODE_NORMAL; + float min = 0f; + float max = 0f; + int iangle = 0; + int oangle = 0; + int outvol = 0; + bool ok = Bass.BASS_ChannelGet3DAttributes(handle, ref mode, ref min, ref max, ref iangle, ref oangle, ref outvol); + + + Dim mode As BASS3DMode = BASS3DMode.BASS_3DMODE_NORMAL + Dim min As Single = 0F + Dim max As Single = 0F + Dim iangle As Integer = 0 + Dim oangle As Integer = 0 + Dim outvol As Integer = 0 + Dim ok As Boolean = Bass.BASS_ChannelGet3DAttributes(handle, mode, min, max, iangle, oangle, outvol) + + + + + + Retrieves the 3D attributes of a sample, stream, or MOD music channel with 3D functionality. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM. + The 3D processing mode (see )... = don't retrieve it. (int) + The minimum distance... = don't retrieve it. (float) + The maximum distance... = don't retrieve it. (float) + The angle of the inside projection cone... = don't retrieve it. (int) + The angle of the outside projection cone... = don't retrieve it. (int) + The delta-volume outside the outer projection cone... = don't retrieve it. (int) + If succesful, then is returned, else is returned. Use to get the error code. + The iangle and oangle parameters must both be retrieved in a single call to this function (ie. you can't retrieve one without the other). See for an explanation of the parameters. + This overload uses native object, so you can specify for some or all parameters in order to not retrieve them. However, the return values of these parameters must be casted back to it's original type. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_NO3DThe channel does not have 3D functionality. + + + + + Only get the delta-volume outside the outer projection cone: + + object outvol = 0; + bool ok = Bass.BASS_ChannelGet3DAttributes(handle, null, null, null, null, null, outvol); + // cast the outvol back it it's normal value type (int) + int deltaVol = (int)outvol; + + + Dim outvol As BASobject = 0 + Dim ok As Boolean = Bass.BASS_ChannelGet3DAttributes(handle, Nothing, Nothing, Nothing, Nothing, Nothing, outvol) + ' cast the outvol back it it's normal value type (int) + Dim deltaVol As Integer = CInt(outvol) + + + + + + Sets the 3D position of a sample, stream, or MOD music channel with 3D functionality. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM. + Position of the sound... = leave current. + Orientation of the sound... = leave current. + Velocity of the sound... = leave current. This is only used to calculate the doppler effect, and has no effect on the sound's position. + If succesful, then is returned, else is returned. Use to get the error code. + As with all 3D functions, must be called to apply the changes made. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_NO3DThe channel does not have 3D functionality. + + + + + + + Retrieves the 3D position of a sample, stream, or MOD music channel with 3D functionality. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM. + Position of the sound... = don't retrieve it. + Orientation of the sound... = don't retrieve it. + Velocity of the sound... = don't retrieve it. + If succesful, then is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_NO3DThe channel does not have 3D functionality. + + + + + + BASS_3DVECTOR pos = new BASS_3DVECTOR(); + BASS_3DVECTOR orient = new BASS_3DVECTOR(); + BASS_3DVECTOR vel = new BASS_3DVECTOR(); + if (Bass.BASS_ChannelGet3DPosition(stream, pos, orient, vel)) + { + Console.WriteLine("{0} : {1} : {2}", pos, orient, vel); + } + + + Dim pos As New BASS_3DVECTOR() + Dim orient As New BASS_3DVECTOR() + Dim vel As New BASS_3DVECTOR() + If Bass.BASS_ChannelGet3DPosition(stream, pos, orient, vel) Then + Console.WriteLine("{0} : {1} : {2}", pos, orient, vel) + End If + + + + + + Sets the playback position of a sample, MOD music, or stream. + + The channel handle... a HCHANNEL, HSTREAM or HMUSIC. + The position, in units determined by the . + How to set the position. One of the following (see ), with optional flags: + + BASS_POS_BYTEThe position is in bytes, which will be rounded down to the nearest sample boundary. + BASS_POS_MUSIC_ORDERThe position is in orders and rows... use . (HMUSIC only). + BASS_POS_DECODETOFlag: Decode/render up to the position rather than seeking to it. This is useful for streams that are unseekable or that have inexact seeking, but it is generally slower than normal seeking and the requested position cannot be behind the current decoding position. This flag can only be used with the BASS_POS_BYTE mode. + BASS_MUSIC_POSRESETFlag: Stop all notes. This flag is applied automatically if it has been set on the channel, eg. via . (HMUSIC). + BASS_MUSIC_POSRESETEXFlag: Stop all notes and reset bpm/etc. This flag is applied automatically if it has been set on the channel, eg. via . (HMUSIC). + + Other modes and flags may be supported by add-ons, see the documentation. + + If succesful, then is returned, else is returned. Use to get the error code. + + Setting the position of a MOD music in bytes (other than 0) requires that the BASS_MUSIC_PRESCAN flag was used in the call. When setting the position in orders/rows, the channel's byte position (as reported by ) is reset to 0. + This is because it's not possible to get the byte position of an order/row position - it's possible that a position may never be played in the normal cause of events, or it may be played multiple times. + When changing the position of a MOD music, and the BASS_MUSIC_POSRESET flag is active on the channel, all notes that were playing before the position changed will be stopped. Otherwise, the notes will continue playing until they are stopped in the MOD music. + When setting the position in bytes, the BPM, "speed" and "global volume" are updated to what they would normally be at the new position. Otherwise they are left as they were prior to the postion change, unless the seek position is 0 (the start), in which case they are also reset to the starting values (when using the BASS_MUSIC_POSRESET flag). + When the BASS_MUSIC_POSRESETEX flag is active, the BPM, speed and global volume are reset with every seek. + For MP3/MP2/MP1 streams, if the BASS_STREAM_PRESCAN flag was used when was called to create the stream, then the seeking will be accurate to the exact requested byte. Exact seeking can also be achieved with the BASS_POS_DECODETO flag. + Otherwise it will be an approximation, which is generally still very accurate. + Note: BASS_STREAM_PRESCAN is ONLY needed for files with a VBR, files with a CBR are always accurate. + + Seeking in internet file (and "buffered" user file) streams is possible once the download has reached the requested position, so long as the file is not being streamed in blocks (BASS_STREAM_BLOCK flag). + User streams (created with ) are not seekable, but it is possible to reset a user stream (including its buffer contents) by setting its position to byte 0. + The BASS_POS_DECODETO flag can be used to seek forwards in streams that are not normally seekable, like custom streams or internet streams that are using the BASS_STREAM_BLOCK flag, but it will only go as far as what is currently available; it will not wait for more data to be downloaded, for example. can be used to confirm what the new position actually is. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_NOTFILEThe stream is not a file stream. + BASS_ERROR_POSITIONThe requested position is invalid, eg. beyond the end. + BASS_ERROR_NOTAVAILThe download has not yet reached the requested position. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Set the position of a stream channel to 10sec. and 200ms: + + Bass.BASS_ChannelSetPosition(stream, Bass.BASS_ChannelSeconds2Bytes(stream, 10.20), BASSMode.BASS_POS_BYTES); + + + Bass.BASS_ChannelSetPosition(stream, Bass.BASS_ChannelSeconds2Bytes(stream, 10.20), BASSMode.BASS_POS_BYTES) + + Set the position of a MOD music to row 20 of order 10: + + Bass.BASS_ChannelSetPosition(music, Utils.MakeMusicPos(10,20), BASSMode.BASS_POS_MUSIC_ORDER ); + + + Bass.BASS_ChannelSetPosition(music, Utils.MakeMusicPos(10,20), BASSMode.BASS_POS_MUSIC_ORDER ) + + Start playback of a MOD music from the beginning of the last order: + + // get number of orders + int len = (int)Bass.BASS_ChannelGetLength(music, BASSMode.BASS_POS_MUSIC_ORDER); + // seek to last order + Bass.BASS_ChannelSetPosition(music, Utils.MakeMusicPos(len-1, 0), BASSMode.BASS_POS_MUSIC_ORDER); + Bass.BASS_ChannelPlay(music, false); // play + + + ' get number of orders + Dim len As Integer = CInt(Bass.BASS_ChannelGetLength(music, BASSMode.BASS_POS_MUSIC_ORDER)) + ' seek to last order + Bass.BASS_ChannelSetPosition(music, Utils.MakeMusicPos(len-1, 0), BASSMode.BASS_POS_MUSIC_ORDER) + Bass.BASS_ChannelPlay(music, False) ' play + + + + + + Sets the playback position in bytes of a sample, MOD music, or stream. + + The channel handle... a HCHANNEL, HSTREAM or HMUSIC. + The position, in bytes. + If succesful, then is returned, else is returned. Use to get the error code. + + Setting the position of a MOD music in bytes requires that the BASS_MUSIC_PRESCAN flag was used in the call. When setting the position in orders/rows, the channel's byte position (as returned by ) is reset to 0. + This is because it's not possible to get the byte position of an order/row position - it's possible that a position may never be played in the normal cause of events, or it may be played multiple times. + When changing the position of a MOD music, and the BASS_MUSIC_POSRESET flag is active on the channel, all notes that were playing before the position changed will be stopped. Otherwise, the notes will continue playing until they are stopped in the MOD music. + When setting the position in bytes, the BPM, "speed" and "global volume" are updated to what they would normally be at the new position. Otherwise they are left as they were prior to the postion change, unless the seek position is 0 (the start), in which case they are also reset to the starting values (when using the BASS_MUSIC_POSRESET flag). + When the BASS_MUSIC_POSRESETEX flag is active, the BPM, speed and global volume are reset with every seek. + When setting the position of a file stream, the position is automatically rounded down to the nearest sample. For MP3/MP2/MP1 streams, if the BASS_STREAM_PRESCAN flag was used when was called to create the stream, then the seeking will be accurate to the exact requested byte. + Otherwise it will be an approximation, which is generally still very accurate. + Note: BASS_STREAM_PRESCAN is ONLY needed for files with a VBR, files with a CBR are always accurate. + + Seeking in internet file (and "buffered" user file) streams is possible once the download has reached the requested position, so long as the file is not being streamed in blocks (BASS_STREAM_BLOCK flag). + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_NOTFILEThe stream is not a file stream. + BASS_ERROR_POSITIONThe requested position is invalid, eg. beyond the end. + BASS_ERROR_NOTAVAILThe download has not yet reached the requested position. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + Set the position of a stream channel to 10sec. and 200ms: + + Bass.BASS_ChannelSetPosition(stream, Bass.BASS_ChannelSeconds2Bytes(stream, 10.20)); + + + Bass.BASS_ChannelSetPosition(stream, Bass.BASS_ChannelSeconds2Bytes(stream, 10.20)) + + + + + + Sets the playback position of a sample or stream to the given seconds value. + + The channel handle... a HCHANNEL or HSTREAM. + The seconds value to set the position to (milliseconds are represented in the fraction part). + If succesful, then is returned, else is returned. Use to get the error code. + This is just an overload which uses and internally. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_NOTFILEThe stream is not a file stream. + BASS_ERROR_POSITIONThe requested position is invalid, eg. beyond the end. + BASS_ERROR_NOTAVAILThe download has not yet reached the requested position. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Sets the playback position in order.row of a MOD music. + + The channel handle... HMUSIC. + The order position. + The row position. + If succesful, then is returned, else is returned. Use to get the error code. + This is just an overload which uses and internally. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_NOTFILEThe stream is not a file stream. + BASS_ERROR_POSITIONThe requested position is invalid, eg. beyond the end. + BASS_ERROR_NOTAVAILThe download has not yet reached the requested position. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Retrieves the playback position of a sample, stream, or MOD music. Can also be used with a recording channel. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM, or HRECORD. + How to retrieve the position. One of the following (see ): + + BASS_POS_BYTEGet the position in bytes. + BASS_POS_MUSIC_ORDERGet the position in orders and rows... LoWord = order, HiWord = row * scaler (). (HMUSIC only). + BASS_POS_DECODEFlag: Get the decoding/rendering position, which may be ahead of the playback position due to buffering. This flag is unnecessary with decoding channels because the decoding position will always be given for them anyway, as they do not have playback buffers. + + Other modes may be supported by add-ons, see the documentation. + + If an error occurs, -1 is returned, use to get the error code. If successful, the position is returned. + With MOD music you might use the and methods to retrieve the order resp. the row values. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_NOTAVAILThe requested position is not available. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + long pos = Bass.BASS_ChannelGetPosition(stream, BASSMode.BASS_POS_BYTES); + + + Dim pos As Long = Bass.BASS_ChannelGetPosition(stream, BASSMode.BASS_POS_BYTES) + + + + + + Retrieves the playback position in bytes of a sample, stream, or MOD music. Can also be used with a recording channel. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM, or HRECORD. + If an error occurs, -1 is returned, use to get the error code. If successful, the position in bytes is returned. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + long pos = Bass.BASS_ChannelGetPosition(stream); + + + Dim pos As Long = Bass.BASS_ChannelGetPosition(stream) + + + + + + Retrieves the level (peak amplitude) of a sample, stream, MOD music or recording channel. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM, or HRECORD. + If an error occurs, -1 is returned, use to get the error code. + If successful, the level of the left channel is returned in the low word (low 16-bits, use ), and the level of the right channel is returned in the high word (high 16-bits, use ). If the channel is mono, then the low word is duplicated in the high word. + The level ranges linearly from 0 (silent) to 32768 (max). 0 will be returned when a channel is stalled. + + + This function measures the level of the channel's sample data, not the level of the channel in the final output mix, + so the channel's volume and panning/balance (as set with , BASS_ATTRIB_VOL or BASS_ATTRIB_PAN) does not affect it. + The effect of any DSP/FX set on the channel is present in the measurement, except for DX8 effects when using the "With FX flag" DX8 effect implementation. + For channels that are more than stereo, the left level will include all left channels (eg. front-left, rear-left, center), and the right will include all right (front-right, rear-right, LFE). + If there are an odd number of channels then the left and right levels will include all channels. If the level of each individual channel is required, that can be calculated from the sample data that provides. + When used with a decoding channel, this function has to decode data (20ms worth) from the channel in order to calculate the level. + Which means that data is gone, eg. it's not available to or other targets anymore! + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_NOPLAYThe channel is not playing. + BASS_ERROR_ENDEDThe decoding channel has reached the end. + BASS_ERROR_BUFLOSTShould not happen... check that a valid window handle was used with . + + + + + Get the left and right levels of a stereo channel: + + int level = Bass.BASS_ChannelGetLevel(channel); + int left = Utils.LowWord32(level); // the left level + int right = Utils.HighWord32(level); // the right level + + + Dim level As Integer = Bass.BASS_ChannelGetLevel(channel) + Dim left As Integer = Utils.LowWord32(level) ' the left level + Dim right As Integer = Utils.HighWord32(level) ' the right level + + + + + + Retrieves the level (peak amplitude) of a sample, stream, MOD music or recording channel. + + The channel handle... a HCHANNEL, HMUSIC, HSTREAM, or HRECORD. + The array which will receive the peak levels values. The size of the array must be set to the number of channels of the stream (e.g. 2 for stereo). + On success is returned - else , use to get the error code. + If successful, the peak levels of the interleaved channel order is returned in the array. + The level value ranges linearly from 0.0 (silent) to 1.0 (=0dB) or above. + + + This function measures the level of the channel's sample data, not the level of the channel in the final output mix, + so the channel's volume and panning/balance (as set with , BASS_ATTRIB_VOL or BASS_ATTRIB_PAN) does not affect it. + The effect of any DSP/FX set on the channel is present in the measurement, except for DX8 effects when using the "With FX flag" DX8 effect implementation. + For channels that are more than stereo, the left level will include all left channels (eg. front-left, rear-left, center), and the right will include all right (front-right, rear-right, LFE). + If there are an odd number of channels then the left and right levels will include all channels. If the level of each individual channel is required, that can be calculated from the sample data that provides. + When used with a decoding channel, this function has to decode data (20ms worth) from the channel in order to calculate the level. + Which means that data is gone, eg. it's not available to or other targets anymore! + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_DATA_AVAILABLEQuery the amount of data the channel has buffered. This flag is primarily of use when recording, and can't be used with decoding channels as they do not have playback buffers. buffer can be when using this flag. + + + + + Get the left and right levels of a stereo channel: + + float[] level = new float[2]; // dealing with stereo + if (Bass.BASS_ChannelGetLevel(channel, level)) + { + float left = level[0]; // the left level + float right = level[1]; // the right level + } + + + Dim level(2) As Single ' dealing with stereo + If Bass.BASS_ChannelGetLevel(channel, level) Then + Dim left As Single = level(0) ' the left level + Dim right As Single = level(1) ' the right level + End If + + + + + + Removes a synchronizer from a MOD music or stream channel. + + The channel handle... a HMUSIC, HSTREAM or HRECORD. + Handle of the synchronizer to remove (return value of a previous call). + If succesful, is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLEAt least one of and is not valid. + + + + + + + Removes a DSP function from a stream, MOD music, or recording channel. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + Handle of the DSP function to remove from the channel (return value of a previous call). + If succesful, is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLEAt least one of and is not valid. + + + + + + + Removes an effect on a stream, MOD music, or recording channel. + + The channel handle... a HSTREAM, HMUSIC, or HRECORD. + Handle of the effect to remove from the channel (return value of a previous call). + If succesful, is returned, else is returned. Use to get the error code. + Depending on the DX8 effect implementation being used by the channel, the channel may have to be stopped before removing a DX8 effect on it. + If necessary, that is done automatically and the channel is resumed afterwards. + can also be used to remove effects. + + + ERROR CODEDescription + BASS_ERROR_HANDLEAt least one of and is not valid. + + + + + + + Links two MOD music or stream channels together. + + The channel handle... a HMUSIC or HSTREAM. + The handle of the channel to have linked with it... a HMUSIC or HSTREAM. + If succesful, is returned, else is returned. Use to get the error code. + + Linked channels are started/stopped/paused/resumed together. Links are one-way, for example, channel will be started by channel , but not vice versa unless another link has been set in that direction. + If a linked channel has reached the end, it will not be restarted when a channel it is linked to is started. If you want a linked channel to be restarted, you need to have resetted it's position using beforehand. + + + ERROR CODEDescription + BASS_ERROR_HANDLEAt least one of and is not a valid channel. + BASS_ERROR_DECODEAt least one of and is a "decoding channel", so can't be linked. + BASS_ERROR_ALREADY is already linked to . + BASS_ERROR_UNKNOWNSome other mystery problem! + + + Platform-specific + Except for on Windows, linked channels on the same device are guaranteed to start playing simultaneously. On Windows, it is possible for there to be a slight gap between them, but it will generally be shorter (and never longer) than starting them individually. + + + Link 2 streams and play them together: + + // link stream2 to stream1 + Bass.BASS_ChannelSetLink(stream1, stream2); + // start both streams together + Bass.BASS_ChannelPlay(stream1, false); + + + ' link stream2 to stream1 + Bass.BASS_ChannelSetLink(stream1, stream2) + ' start both streams together + Bass.BASS_ChannelPlay(stream1, False) + + + + + + Removes a links between two MOD music or stream channels. + + The channel handle... a HMUSIC or HSTREAM. + The handle of the channel to have unlinked with it... a HMUSIC or HSTREAM. + If succesful, is returned, else is returned. Use to get the error code. + + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not a valid channel. + BASS_ERROR_ALREADYEither is not a valid channel, or it is already not linked to . + + + + + + + Retrieves the requested tags/headers from a channel, if they are available. + + The channel handle...a HMUSIC or HSTREAM. + The tags/headers wanted... one of the following (see ): + + BASS_TAG_ID3ID3v1 tags. A pointer to a 128 byte block is returned. See www.id3.org for details of the block's structure. + BASS_TAG_ID3V2ID3v2 tags. A pointer to a variable length block is returned. See www.id3.org for details of the block's structure. ID3v2 tags are supported at both the start and end of the file. + BASS_TAG_LYRICS3Lyrics3v2 tag. A single string is returned, containing the Lyrics3v2 information. See www.id3.org/Lyrics3v2 for details of its format. + BASS_TAG_APEAPE (v1 or v2) tags. A pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. Each string is in the form of "key=value", or "key=value1/value2/..." if there are multiple values. + BASS_TAG_APE_BINARY+ tag number (0=first). APEv2 binary tag. A pointer to a structure is returned. + BASS_TAG_OGGOGG comments, only available when streaming an OGG file. A pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. + BASS_TAG_MFMedia Foundation metadata. A pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. + BASS_TAG_VENDOROGG encoder. A single UTF-8 string is returned. + BASS_TAG_HTTPHTTP headers, only available when streaming from a HTTP server. A pointer to a series of null-terminated strings is returned, the final string ending with a double null. + BASS_TAG_ICYICY (Shoutcast) tags. A pointer to a series of null-terminated strings is returned, the final string ending with a double null. + BASS_TAG_METAShoutcast metadata. A single null-terminated string containing the current stream title and url (usually omitted). The format of the string is: StreamTitle='xxx';StreamUrl='xxx'; + BASS_TAG_RIFF_INFORIFF/WAVE 'INFO' tags. A pointer to a series of null-terminated ANSI strings is returned, the final string ending with a double null. The tags are in the form of 'XXXX=text', where 'XXXX' is the chunk ID. + BASS_TAG_RIFF_DISPRIFF/WAVE 'DISP' chunk text (CF_TEXT) tag. A single string is returned. + BASS_TAG_RIFF_BEXTRIFF/BWF "bext" chunk tags. A pointer to a structure is returned. + BASS_TAG_RIFF_CARTRIFF/BWF "cart" chunk tags. A pointer to a structure is returned. + BASS_TAG_WAVEFORMATWAVE "fmt" chunk contents. A pointer to a WAVEFORMATEX structure is returned. As well as WAVE files, this is also provided by Media Foundation codecs. + BASS_TAG_CA_CODECCoreAudio codec information. A pointer to a structure is returned. + BASS_TAG_MUSIC_NAMEMOD music title (a single null-terminated ANSI String). + BASS_TAG_MUSIC_MESSAGEMOD message text (a single null-terminated ANSI String). + BASS_TAG_MUSIC_INST+ instrument number (0=first). MOD instrument name (a single null-terminated ANSI String). + BASS_TAG_MUSIC_SAMPLE+ sample number (0=first). MOD sample name (a single null-terminated ANSI String). + BASS_TAG_MUSIC_ORDERSMOD music order list. A pointer to a byte array is returned, with each byte being the pattern number played at that order position. Pattern number 254 is "+++" (skip order) and 255 is "---" (end song). + + Other tags may be supported by Add-Ons, see the documentation. + + If succesful, a pointer to the data of the tags/headers is returned, else is returned. Use to get the error code. + + Some tags (eg. ID3v1) are located at the end of the file, so when streaming a file from the internet, the tags will not be available until the download is complete. A BASS_SYNC_DOWNLOAD sync can be set via , to be informed of when the download is complete. + A BASS_SYNC_META sync can be used to be informed of new Shoutcast metadata, and a BASS_SYNC_OGG_CHANGE sync for when a new logical bitstream begins in a chained OGG stream, which generally brings new OGG tags. + When a Media Foundation codec is in use, the BASS_TAG_WAVEFORMAT tag can be used to find out what the source format is, eg. via the WAVEFORMATEX structure's wFormatTag member. Some typical wFormatTag examples are: 0x0161 = WMA, 0x0162 = WMA pro, 0x0163 = WMA lossless, 0x1610 = AAC. + You might also use one of these overloads to directly get specific tags: + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + . + + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + Getting OGG Tags: + + int channel = Bass.BASS_StreamCreateFile("test.ogg", 0, 0, BASSFlag.BASS_SAMPLE_FLOAT); + IntPtr tag = Bass.BASS_ChannelGetTags(channel, BASSTag.BASS_TAG_OGG); + string[] tags = Utils.IntPtrToArrayNullTermUtf8(tag); + if (tags != null) + { + foreach (string tag in tags) + Console.Writeln("Tag: {0}\n", tag); + } + + + Dim channel As Integer = Bass.BASS_StreamCreateFile("test.ogg", 0, 0, BASSFlag.BASS_SAMPLE_FLOAT) + Dim tag As IntPtr = Bass.BASS_ChannelGetTags(channel, BASSTag.BASS_TAG_OGG) + Dim tags As String() = Utils.IntPtrToArrayNullTermUtf8(tag) + If Not (tags Is Nothing) Then + Dim tag As String + For Each tag In tags + Console.Writeln("Tag: {0}" + ControlChars.Lf, tag) + Next tag + End If + + Getting MOD Music Instruments: + + IntPtr p = BASS_ChannelGetTags(handle, (BASSTag)(BASSTag.BASS_TAG_MUSIC_INST + instrument)); + if (p != IntPtr.Zero) + string instr = Marshal.PtrToStringAnsi(p); + + + Dim p As IntPtr = BASS_ChannelGetTags(handle, CType(BASSTag.BASS_TAG_MUSIC_INST + instrument, BASSTag)) + If p <> IntPtr.Zero Then + Dim instr As String = Marshal.PtrToStringAnsi(p) + End If + + + + + + Retrieves the header tags from a channel, if they are available. + NOTE: This method evaluates the header as a series/array of null-terminated Ansi strings. + Might be used e.g. with: RIFF_INFO, ICY and HTTP. + + The stream's handle. + The type of tags/headers wanted... one of the following (see ): + + BASS_TAG_HTTPHTTP headers, only available when streaming from a HTTP server. A pointer to a series of null-terminated strings is returned, the final string ending with a double null. + BASS_TAG_ICYICY (Shoutcast) tags. A pointer to a series of null-terminated strings is returned, the final string ending with a double null. + BASS_TAG_RIFF_INFORIFF/WAVE 'INFO' tags. A pointer to a series of null-terminated ANSI strings is returned, the final string ending with a double null. The tags are in the form of 'XXXX=text', where 'XXXX' is the chunk ID. + + Other tags may be supported by Add-Ons, see the documentation (ASNI only). + + or an array of strings. Each array element will represent one tag, e.g. "TITLE=this is a title" + + + Only available when streaming a file containing tags/headers which are defined as a series of null-terminated ASNI strings! So make sure to use this method only with appropriate formats! + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + + Retrieves the header tags from a channel, if they are available. + NOTE: This method evaluates the header as a series/array of null-terminated UTF-8 strings. + Might be used e.g. with: APE, MP4, OGG and WMA - if UTF-8! + + The channel handle...a HMUSIC or HSTREAM. + The type of tags/headers wanted... one of the following (see ): + + BASS_TAG_OGGOGG tags, only available when streaming an OGG file. A pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. + BASS_TAG_VENDORVendor encoder tag. A single UTF-8 string is returned. + BASS_TAG_WMAWMA tags : array of null-terminated UTF-8 strings. + BASS_TAG_WMA_METAWMA mid-stream tag : A single UTF-8 string is returned. + BASS_TAG_WMA_CODECWMA codec tag : Two UTF-8 strings are returned. + BASS_TAG_APEAPE tags. A pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. Each string is in the form of "key=value", or "key=value1/value2/..." if there are multiple values. + BASS_TAG_MP4MP4 tags. A pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. + BASS_TAG_MFMedia Foundation metadata. A pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. + + Other tags may be supported by Add-Ons, see the documentation - only UTF-8! + + or an array of strings. Each array element will represent one tag, e.g. "TITLE=this is a title" + + Only available when streaming a file containing tags/headers which are defined as a series of null-terminated UNICODE strings! So make sure to use this method only with appropriate formats! + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + + Retrieves the ID3v1 tags from a channel, if they are available. + This special helper method already evaluates the 128-byte ID3v3 data block. + + The channel handle...a HSTREAM. + or an array of strings with exactly 7 elements: + string[0] = 'song title' (max. 30 chars) + string[1] = 'artist' (max. 30 chars) + string[2] = 'album' (max. 30 chars) + string[3] = 'year' (yyyy) + string[4] = 'comment' (max. 28 chars) + string[5] = 'genre-id' + string[6] = 'track' (0-255) + + + ID3v1 tags are located at the end of the file, so when streaming an MPEG file with ID3v1 tags from the internet, the tags will not be available until the download is complete. + A BASS_SYNC_DOWNLOAD sync can be set via , to be informed of when the download is complete. + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_DEFAULT); + string[] tags = Bass.BASS_ChannelGetTagsID3V1(stream); + foreach (string tag in tags) + Console.WriteLine(tag); + + + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_DEFAULT) + Dim tags As String() = Bass.BASS_ChannelGetTagsID3V1(stream) + Dim tag As String + For Each tag In tags + Console.WriteLine(tag) + Next tag + + + + + + Retrieves the Broadcast Audio Extension (BEXT) tags from a channel, if they are available. + This special helper method already evaluates the BEXT data block. + + The channel handle...a HSTREAM. + or an array of strings with exactly 9 elements: + string[0] = Description/Title (max. 256 chars) + string[1] = Originator/Artist (max. 32 chars) + string[2] = OriginatorReference/EncodedBy (max. 32 chars) + string[3] = OriginationDate (in format 'yyyy-mm-dd') + string[4] = OriginationTime (in format 'hh:mm:ss') + string[5] = TimeReference (in samples since midnight) + string[6] = Version (BWF version is typically 0 or 1) + string[7] = UMID/Copyright (max. 64 chars) + string[8] = CodingHistory/Comment + + + More info about the BWF/RF64 tags (Broadcast Audio Extension) can be found here: EBU specification. + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + + Retrieves the CoreAudio codec information structure from a channel, if they are available. + + The channel handle...a HSTREAM. + or an instance of the array of strings with exactly 9 elements: + string[0] = Description/Title (max. 256 chars) + string[1] = Originator/Artist (max. 32 chars) + string[2] = OriginatorReference/EncodedBy (max. 32 chars) + string[3] = OriginationDate (in format 'yyyy-mm-dd') + string[4] = OriginationTime (in format 'hh:mm:ss') + string[5] = TimeReference (in samples since midnight) + string[6] = Version (BWF version is typically 0 or 1) + string[7] = UMID/Copyright (max. 64 chars) + string[8] = CodingHistory/Comment + + + More info about the BWF/RF64 tags (Broadcast Audio Extension) can be found here: EBU specification. + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + + Retrieves the ID3v2 header tags from a channel, if they are available. + + The channel handle...a HSTREAM. + or an array of strings. Each array element will represent one tag in the format 'FrameId=Value' (e.g. "TIT2=This is a Title"). + Only tag values containing strings are returned (e.g. Txxx, Wxxx or COMM tags). + ID3v2 tags are supported at both the start and end of the file. + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + Invalid/Unsupported ID3v2 version detected. + + + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_DEFAULT); + string[] tags = Bass.BASS_ChannelGetTagsID3V2(stream); + foreach (string tag in tags) + Console.WriteLine(tag); + + + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_DEFAULT) + Dim tags As String() = Bass.BASS_ChannelGetTagsID3V2(stream) + Dim tag As String + For Each tag In tags + Console.WriteLine(tag) + Next tag + + + + + + Retrieves the APE (v1 or v2) header tags from a channel, if they are available. + This special helper method already evaluates the null-terminated and variable length data block using UTF-8 strings. + + The channel handle. + or an array of strings. Each array element will represent one tag in the format 'TagName=Value' (e.g. "TITLE=This is a Title"). + + Only available when streaming a file containing APE tags. + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + Bass.BASS_PlugInLoad("bass_ape.dll"); + ... + int stream = Bass.BASS_StreamCreateFile("test.ape", 0, 0, BASSFlag.BASS_DEFAULT); + string[] tags = Bass.BASS_ChannelGetTagsAPE(stream); + foreach (string tag in tags) + Console.WriteLine(tag); + + + Bass.BASS_PlugInLoad("bass_ape.dll") + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.ape", 0, 0, BASSFlag.BASS_DEFAULT) + Dim tags As String() = Bass.BASS_ChannelGetTagsAPE(stream) + Dim tag As String + For Each tag In tags + Console.WriteLine(tag) + Next tag + + + + + + Retrieves all APE binary tags from a channel, if they are available. + + The channel handle. + or an array of instances. + + Only available when streaming a file containing APE tags. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + Bass.BASS_PlugInLoad("basswv.dll"); + ... + int stream = Bass.BASS_StreamCreateFile("test.wv", 0, 0, BASSFlag.BASS_DEFAULT); + BASS_TAG_APE_BINARY[] binTags = Bass.BASS_ChannelGetTagsAPEBinary(stream); + + + Bass.BASS_PlugInLoad("basswv.dll") + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.wv", 0, 0, BASSFlag.BASS_DEFAULT) + Dim binTags As BASS_TAG_APE_BINARY() = Bass.BASS_ChannelGetTagsAPEBinary(stream) + + + + + + Retrieves all APEv2 picture tags from a channel, if they are available. + + The channel handle. + or an array of instances. + + Only available when streaming a file containing APE tags. + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + Bass.BASS_PlugInLoad("basswv.dll"); + ... + int stream = Bass.BASS_StreamCreateFile("test.wv", 0, 0, BASSFlag.BASS_DEFAULT); + AddOn.Tags.TagPicture[] pics = Bass.BASS_ChannelGetTagsAPEPictures(stream); + + + Bass.BASS_PlugInLoad("basswv.dll") + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.wv", 0, 0, BASSFlag.BASS_DEFAULT) + Dim pics As AddOn.Tags.TagPicture() = Bass.BASS_ChannelGetTagsAPEPictures(stream) + + + + + + Retrieves the WMA header tags or mid-stream tags from a channel, if they are available. + This special helper method already evaluates the null-terminated and variable length data block using UTF-8 strings. + + The channel handle. + or an array of strings. Each array element will represent one tag in the format 'AttribName=Value' (e.g. "TITLE=This is a Title"). + + Only available when streaming a file containing WMA tags. + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + Bass.BASS_PlugInLoad("basswma.dll"); + ... + int stream = Bass.BASS_StreamCreateFile("test.wma", 0, 0, BASSFlag.BASS_DEFAULT); + string[] tags = Bass.BASS_ChannelGetTagsWMA(stream); + foreach (string tag in tags) + Console.WriteLine(tag); + + + Bass.BASS_PlugInLoad("basswma.dll") + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.wma", 0, 0, BASSFlag.BASS_DEFAULT) + Dim tags As String() = Bass.BASS_ChannelGetTagsWMA(stream) + Dim tag As String + For Each tag In tags + Console.WriteLine(tag) + Next tag + + + + + + Retrieves the MP4 header tags from a channel, if they are available. + This special helper method already evaluates the null-terminated and variable length data block using UTF-8 strings. + + The channel handle. + or an array of strings. Each array element will represent one tag in the format 'TagName=Value' (e.g. "TITLE=This is a Title"). + + Only available when streaming a file containing MP4 tags. + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + Bass.BASS_PlugInLoad("bass_aac.dll"); + ... + int stream = Bass.BASS_StreamCreateFile("test.m4a", 0, 0, BASSFlag.BASS_DEFAULT); + string[] tags = Bass.BASS_ChannelGetTagsMP4(stream); + foreach (string tag in tags) + Console.WriteLine(tag); + + + Bass.BASS_PlugInLoad("bass_aac.dll") + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.m4a", 0, 0, BASSFlag.BASS_DEFAULT) + Dim tags As String() = Bass.BASS_ChannelGetTagsMP4(stream) + Dim tag As String + For Each tag In tags + Console.WriteLine(tag) + Next tag + + + + + + Retrieves the Media Foundation tags from a channel, if they are available. + This special helper method already evaluates the null-terminated and variable length data block using UTF-8 strings. + + The channel handle. + or an array of strings. Each array element will represent one tag in the format 'TagName=Value' (e.g. "TITLE=This is a Title"). + + Only available when streaming a file using a Media Foundation codec (available on Windows7 and updated Vista only). + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + ... + int stream = Bass.BASS_StreamCreateFile("test.m4a", 0, 0, BASSFlag.BASS_DEFAULT); + string[] tags = Bass.BASS_ChannelGetTagsMF(stream); + foreach (string tag in tags) + Console.WriteLine(tag); + + + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.m4a", 0, 0, BASSFlag.BASS_DEFAULT) + Dim tags As String() = Bass.BASS_ChannelGetTagsMF(stream) + Dim tag As String + For Each tag In tags + Console.WriteLine(tag) + Next tag + + + + + + Retrieves the WAVE "fmt" chunk contents ( structure). + As well as WAVE files, this is also provided by Media Foundation codecs. + + The channel handle. + or an instance of the structure on success. + + Only available when streaming a file using a Media Foundation codec (available on Windows7 and updated Vista only) or a WAVE file. + When a Media Foundation codec is in use, the structure's wFormatTag member can be used to find out what the source format is. + Some typical wFormatTag examples are: 0x0161 = WMA, 0x0162 = WMA_PRO, 0x0163 = WMA_LOSSLESS, 0x1610 = MPEG_HEAAC. + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + + Retrieves all FLAC picture tags from a channel, if they are available. + + The channel handle. + or an array of instances. + + Only available when streaming a file containing FLAC tags. + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + Bass.BASS_PlugInLoad("bassflac.dll"); + ... + int stream = Bass.BASS_StreamCreateFile("test.flac", 0, 0, BASSFlag.BASS_DEFAULT); + BASS_TAG_FLAC_PICTURE[] pics = Bass.BASS_ChannelGetTagsFLACPictures(stream); + + + Bass.BASS_PlugInLoad("bassflac.dll") + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.flac", 0, 0, BASSFlag.BASS_DEFAULT) + Dim pics As BASS_TAG_FLAC_PICTURE() = Bass.BASS_ChannelGetTagsFLACPictures(stream) + + + + + + Retrieves a FLAC cuesheet tags from a channel, if available. + + The channel handle. + or an instance of the . + + Only available when streaming a file containing FLAC tags. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + Bass.BASS_PlugInLoad("bassflac.dll"); + ... + int stream = Bass.BASS_StreamCreateFile("test.flac", 0, 0, BASSFlag.BASS_DEFAULT); + BASS_TAG_FLAC_CUE cuesheet = Bass.BASS_ChannelGetTagsFLACCuesheet(stream); + + + Bass.BASS_PlugInLoad("bassflac.dll") + ... + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.flac", 0, 0, BASSFlag.BASS_DEFAULT) + Dim cuesheet As BASS_TAG_FLAC_CUE = Bass.BASS_ChannelGetTagsFLACCuesheet(stream) + + + + + + Retrieves the HTTP header tags from a channel, if they are available. + This special helper method already evaluates the null-terminated and variable length data block using ANSI strings. + + The channel handle. + or an array of strings. Each array element will represent one header entry, e.g. "Server: Icecast 2.2.0" + + + Only available when streaming from a HTTP source. + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + int stream = Bass.BASS_StreamCreateURL("http://www.radio42.com/playHiFi.pls", 0, + BASSFlag.BASS_STREAM_STATUS, null, IntPtr.Zero); + string[] tags = Bass.BASS_ChannelGetTagsICY(stream); + if (tags == null) + { + // try http... + tags = Bass.BASS_ChannelGetTagsHTTP(stream); + } + if (tags != null) + { + foreach (string tag in tags) + Console.WriteLine(tag); + } + + + Dim stream As Integer = Bass.BASS_StreamCreateURL("http://www.radio42.com/playHiFi.pls", 0, + BASSFlag.BASS_STREAM_STATUS, Nothing, IntPtr.Zero) + Dim tags As String() = Bass.BASS_ChannelGetTagsICY(stream) + If tags Is Nothing Then + ' try http... + tags = Bass.BASS_ChannelGetTagsHTTP(stream) + End If + If Not (tags Is Nothing) Then + Dim tag As String + For Each tag In tags + Console.WriteLine(tag) + Next tag + End If + + + + + + Retrieves the ICY (Shoutcast) tags from a channel, if they are available. + This special helper method already evaluates the null-terminated and variable length data block using ANSI strings. + + The channel handle. + or an array of strings. Each array element will represent one ICY entry, e.g. "icy-name: name of the stream" + + + Only available when streaming from Shoutcast. + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + int stream = Bass.BASS_StreamCreateURL("http://www.radio42.com/playHiFi.pls", 0, + BASSFlag.BASS_STREAM_STATUS, null, IntPtr.Zero); + string[] tags = Bass.BASS_ChannelGetTagsICY(stream); + if (tags == null) + { + // try http... + tags = Bass.BASS_ChannelGetTagsHTTP(stream); + } + if (tags != null) + { + foreach (string tag in tags) + Console.WriteLine(tag); + } + + + Dim stream As Integer = Bass.BASS_StreamCreateURL("http://www.radio42.com/playHiFi.pls", 0, + BASSFlag.BASS_STREAM_STATUS, Nothing, IntPtr.Zero) + Dim tags As String() = Bass.BASS_ChannelGetTagsICY(stream) + If tags Is Nothing Then + ' try http... + tags = Bass.BASS_ChannelGetTagsHTTP(stream) + End If + If Not (tags Is Nothing) Then + Dim tag As String + For Each tag In tags + Console.WriteLine(tag) + Next tag + End If + + + + + + Retrieves the OGG tags from a channel, if they are available. + This special helper method already evaluates the null-terminated and variable length data block using UTF-8 strings. + + The channel handle. + or an array of strings. Each array element will represent one tag in the format 'TagName=Value' (e.g. "TITLE=This is a Title"). + + Only available when streaming an OGG file. + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + int stream = Bass.BASS_StreamCreateFile("test.ogg", 0, 0, BASSFlag.BASS_DEFAULT); + string[] tags = Bass.BASS_ChannelGetTagsOGG(stream); + foreach (string tag in tags) + Console.WriteLine(tag); + + + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.ogg", 0, 0, BASSFlag.BASS_DEFAULT) + Dim tags As String() = Bass.BASS_ChannelGetTagsOGG(stream) + Dim tag As String + For Each tag In tags + Console.WriteLine(tag) + Next tag + + + + + + Retrieves the RIFF/WAVE Info tags from a channel, if they are available. + This special helper method already evaluates the null-terminated and variable length data block using ANSI strings. + + The channel handle. + or an array of strings. Each array element will represent one tag in the format 'ID=Value' (e.g. "IART =This is the Artist"). + + Only available for RIFF/WAVE files. + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + int stream = Bass.BASS_StreamCreateFile("test.wav", 0, 0, BASSFlag.BASS_DEFAULT); + string[] tags = Bass.BASS_ChannelGetTagsRIFF(stream); + foreach (string tag in tags) + Console.WriteLine(tag); + + + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.wav", 0, 0, BASSFlag.BASS_DEFAULT) + Dim tags As String() = Bass.BASS_ChannelGetTagsRIFF(stream) + Dim tag As String + For Each tag In tags + Console.WriteLine(tag) + Next tag + + + + + + Retrieves metadata tags from a channel (Shoutcast or Icecast), if they are available. + + The channel handle. + or an array of strings. Each array element will represent one tag in the format 'Name=Value' (e.g. "StreamTitle='xyz'"). + + Only available when streaming from Shoutcast. + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + int stream = Bass.BASS_StreamCreateURL("http://www.radio42.com/playHiFi.pls", 0, + BASSFlag.BASS_STREAM_STATUS, null, IntPtr.Zero); + string[] tags = Bass.BASS_ChannelGetTagsMETA(stream); + if (tags != null) + { + foreach (string tag in tags) + Console.WriteLine(tag); + } + + + Dim stream As Integer = Bass.BASS_StreamCreateURL("http://www.radio42.com/playHiFi.pls", 0, + BASSFlag.BASS_STREAM_STATUS, Nothing, IntPtr.Zero) + Dim tags As String() = Bass.BASS_ChannelGetTagsMETA(stream) + If Not (tags Is Nothing) Then + Dim tag As String + For Each tag In tags + Console.WriteLine(tag) + Next tag + End If + + + + + + Retrieves a Lyrics3v2 tag. + + The channel handle. + A single string is returned, containing the Lyrics3v2 information - or , if not available. + See www.id3.org/Lyrics3v2 for details of its format. + + + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + + Retrieves the MOD music title from a channel, if it is available. + + The channel handle...a HMUSIC. + or a single string representing the MOD music title. + + Only available for MOD music channels. + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + + Retrieves the MOD message text from a channel, if it is available. + + The channel handle...a HMUSIC. + or a single string representing the MOD message text. + + Only available for MOD music channels. + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + + Retrieves a specific MOD instrument name from a channel, if it is available. + + The channel handle...a HMUSIC. + The instrument number (0=first). + or a single string representing the MOD instrument name. + + Only available for MOD music channels. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + + Retrieves a specific MOD sample name from a channel, if it is available. + + The channel handle...a HMUSIC. + The sample number (0=first). + or a single string representing the MOD sample name. + + Only available for MOD music channels. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + List all MOD music's samples: + + string name = String.Empty; + int i = 0; + while ( true ) + { + name = Bass.BASS_ChannelGetMusicSample( mod, i ); + if ( name != null ) + Console.Writeln( String.Format( "Sample {0}={1}", i, name ) ); + else + break; + i++; + } + + + Dim name As String = [String].Empty + Dim i As Integer = 0 + While True + name = Bass.BASS_ChannelGetMusicSample([mod], i) + If Not (name Is Nothing) Then + Console.Writeln([String].Format("Sample {0}={1}", i, name)) + Else + Exit While + End If + i += 1 + End While + + + + + + Retrieves a specific MIDI track text from a channel, if it is available. + + The channel handle...a MIDI HSTREAM. + The MIDI track number (0=first), use -1 to get the text for all tracks. + or an array of strings. Each array element will represent one text of the MIDI track. + + The texts of each track in the MIDI file are available via the +track tag, where track=0 is the first track. + The first text in the first track is generally the title of the MIDI file. + RIFF MIDI tags are also available via the standard tag. + In addition you might also use the class, which provides extended TAG reading support. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_NOTAVAILThe requested tags are not available. + + + + + + + + + + + + + + + Sets the parameters of an effect. + + The effect handle. + An instance of an effect parameter structures. + Additional effect parameter structures might be implemented by add-ons. + + If successful, is returned, else is returned. Use to get the error code. + + The structure used depends on the effect type. + For DX8 effects you might use: , , , , , , , , . + For BASS_FX DSP effetcs you might use: , , , , , , , , , , , , , , . + Use to add an effect DSP to a channel at anay time and to remove an effect from the channel. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_ILLPARAMOne or more of the parameters are invalid, make sure all the values are within the valid ranges. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + int stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_DEFAULT); + BASS_DX8_ECHO echo = new BASS_DX8_ECHO(); + // add the effect to the DSP chain + int fxHandle = Bass.BASS_ChannelSetFX(stream, BASSFXType.BASS_FX_ECHO, 0); + echo.Preset_Long(); + // apply the effect parameters + Bass.BASS_FXSetParameters(fxHandle, echo); + // play the channel + Bass.BASS_ChannelPlay(stream, false); + + + Dim stream As Integer = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_DEFAULT) + Dim echo As New BASS_DX8_ECHO() + ' add the effect to the DSP chain + Dim fxHandle As Integer = Bass.BASS_ChannelSetFX(stream, BASSFXType.BASS_FX_ECHO, 0) + echo.Preset_Long() + ' apply the effect parameters + Bass.BASS_FXSetParameters(fxHandle, echo) + ' play the channel + Bass.BASS_ChannelPlay(stream, False) + + + + + + + + + + + + + + Retrieves the parameters of an effect. + + The effect handle. + An instance of an effect parameter structures which should be filled. + Additional effect parameter structures might be implemented by add-ons. + + If successful, is returned, else is returned. Use to get the error code. + + The structure used depends on the effect type. + For DX8 effects you might use: , , , , , , , , . + For BASS_FX DSP effetcs you might use: , , , , , , , , , , , , , , , . + Use to add an effect DSP to a channel at anay time and to remove an effect from the channel. + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + + + + + + BASS_DX8_ECHO echo = new BASS_DX8_ECHO(); + Bass.BASS_FXGetParameters(_fxEchoHandle, echo); + Console.WriteLine( "Panning={0}", echo.lPanDelay ); + + + Dim echo As New BASS_DX8_ECHO() + Bass.BASS_FXGetParameters(_fxEchoHandle, echo) + Console.WriteLine("Panning={0}", echo.lPanDelay) + + + + + + Resets the state of an effect or all effects on a channel. + + The effect or channel handle... a HFX, HSTREAM, HMUSIC, or HRECORD. + If successful, is returned, else is returned. Use to get the error code. + Call this function e.g. after changing the position or when you pause a channel or when a stream stalls to avoid clicks when resuming. + This function flushes the internal buffers of the effect(s). Effects are automatically reset by , except when called from a "mixtime" . + + + ERROR CODEDescription + BASS_ERROR_HANDLE is not valid. + BASS_ERROR_UNKNOWNSome other mystery problem! + + + + + + + Supported stream file extensions of the bass.dll. + + + Note: This list reports a set of file extensions which might be supported by BASS. + There is no guarantee that the list is complete or might contain formats not being supported on your particular OS. + + + + + Supported file format name of the bass.dll. + + + Note: This list reports a set of file formats which might be supported by BASS. + There is no guarantee that the list is complete or might contain formats not being supported on your particular OS. + + + + + Supported music file extensions of the bass.dll. + + + + + Was the BASS_CONFIG_UNICODE option set? + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + Load BASS and BASSWMA from the application's startup path: + + Bass.LoadMe(); + BassWma.LoadMe(); + ... + // when not used anymore... + BassWma.FreeMe(); + Bass.FreeMe(); + + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + Load BASS and BASSWMA from a different directory: + + Bass.LoadMe( @"C:\Development\BASS\_libs" ); + BassWma.LoadMe( @"C:\Development\BASS\_libs" ); + ... + // when not used anymore... + BassWma.FreeMe(); + Bass.FreeMe(); + + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + + Gets, if BASS leverages additional Windows Media Foundation audio codecs as installed with the OS. + + + + + Gets, if BASS leverages additional Apple Core Audio Format audio codecs as installed with the OS (MacOSX only). + + + + + BASS error codes as returned e.g. by (int) + + + + + All is OK + + + + + Memory error + + + + + Can't open the file + + + + + Can't find a free/valid driver + + + + + The sample buffer was lost + + + + + Invalid handle + + + + + Unsupported sample format + + + + + Invalid playback position + + + + + BASS_Init has not been successfully called + + + + + BASS_Start has not been successfully called + + + + + No CD in drive + + + + + Invalid track number + + + + + Already initialized/paused/whatever + + + + + Not paused + + + + + Not an audio track + + + + + Can't get a free channel + + + + + An illegal type was specified + + + + + An illegal parameter was specified + + + + + No 3D support + + + + + No EAX support + + + + + Illegal device number + + + + + Not playing + + + + + Illegal sample rate + + + + + The stream is not a file stream + + + + + No hardware voices available + + + + + The MOD music has no sequence data + + + + + No internet connection could be opened + + + + + Couldn't create the file + + + + + Effects are not available + + + + + The channel is playing + + + + + Requested data is not available + + + + + The channel is a 'decoding channel' + + + + + A sufficient DirectX version is not installed + + + + + Connection timedout + + + + + Unsupported file format + + + + + Unavailable speaker + + + + + Invalid BASS version (used by add-ons) + + + + + Codec is not available/supported + + + + + The channel/file has ended + + + + + The device is busy (eg. in "exclusive" use by another process) + + + + + Some other mystery error + + + + + BassWma: the file is protected + + + + + BassWma: WM9 is required + + + + + BassWma: access denied (user/pass is invalid) + + + + + BassWma: no appropriate codec is installed + + + + + BassWma: individualization is needed + + + + + BassEnc: ACM codec selection cancelled + + + + + BassEnc: Access denied (invalid password) + + + + + BassVst: the given effect has no inputs and is probably a VST instrument and no effect + + + + + BassVst: the given effect has no outputs + + + + + BassVst: the given effect does not support realtime processing + + + + + BassFx: Not a decoding channel + + + + + BassFx: BPM detection is in use + + + + + BASSVIDEO: Action was abort + + + + + BASSVIDEO: Cannot connect filter / pin. + + + + + BASSVIDEO: Cannot read file. + + + + + BASSVIDEO: Cannot write file. + + + + + BASSVIDEO: Failure to do. + + + + + BASSVIDEO: Error cause by filter. + + + + + BASSVIDEO: Invalid BassVideo channel. + + + + + BASSVIDEO: Wrong dll. + + + + + BASSVIDEO: Invalid format. + + + + + BASSVIDEO: Invalid handle. + + + + + BASSVIDEO: Invalid parameter. + + + + + BASSVIDEO: No sound. + + + + + BASSVIDEO: No "Video Effect" detected. + + + + + BASSVIDEO: Failed to querry interface. + + + + + BASSVIDEO: No renderer. + + + + + BASSVIDEO: No support/Currently not supported. + + + + + BASSVIDEO: No Video. + + + + + BASSVIDEO: Not allowed. + + + + + BASSVIDEO: Filter/Pin had not connected. + + + + + BASSVIDEO: Not existing object. + + + + + BASSVIDEO: Object not found + + + + + BASSVIDEO: Graph/Filter not ready. + + + + + BASSVIDEO: Device is null. + + + + + BASSVIDEO: Cannot open. + + + + + BASSVIDEO: Not enough memory. + + + + + BASSVIDEO: Stream is in an unsupported format. + + + + + BASSVIDEO: A Timeout occured. + + + + + BASSVIDEO: Unknown file type. + + + + + BASSVIDEO: Cannot play file, format not supported. + + + + + BASSVIDEO: Cannot create video filter. + + + + + BASSWASAPI: no WASAPI available + + + + + Initialization flags to be used with + + + + + 0 = 16 bit, stereo, no 3D, no Latency calc, no Speaker Assignments + + + + + Use 8 bit resolution, else 16 bit. + + + + + Use mono, else stereo. + + + + + Enable 3D functionality. + Note: If the BASS_DEVICE_3D flag is not specified when initilizing BASS, + then the 3D flags (BASS_SAMPLE_3D and BASS_MUSIC_3D) are ignored when + loading/creating a sample/stream/music. + + + + + Calculate device latency (BASS_INFO struct). + + + + + Use the Windows control panel setting to detect the number of speakers. + Only use this option if BASS doesn't detect the correct number of supported speakers automatically and you want to force BASS to use the number of speakers as configured in the windows control panel. + + + + + Force enabling of speaker assignment (always 8 speakers will be used regardless if the soundcard supports them). + Only use this option if BASS doesn't detect the correct number of supported speakers automatically and you want to force BASS to use 8 speakers. + + + + + ignore speaker arrangement + + + + + Linux-only: Initialize the device using the ALSA "dmix" plugin, else initialize the device for exclusive access. + + + + + Set the device's output rate to freq, otherwise leave it as it is. + + + + + Direct Sound interface flags for use with + + + + + Retrieve the IDirectSound interface. + + + + + Retrieve the IDirectSound3DListener interface. + + + + + Configuration options to be used with , and , . + + + + + Playback buffer length. + length (int): The buffer length in milliseconds. The minimum length is 1ms above the update period (see ), the maximum is 5000 milliseconds. If the length specified is outside this range, it is automatically capped. + The default buffer length is 500 milliseconds. Increasing the length, decreases the chance of the sound possibly breaking-up on slower computers, but also increases the latency for DSP/FX. + Small buffer lengths are only required if the sound is going to be changing in real-time, for example, in a soft-synth. If you need to use a small buffer, then the minbuf member of BASS_INFO should be used to get the recommended minimum buffer length supported by the device and it's drivers. Even at this default length, it's still possible that the sound could break up on some systems, it's also possible that smaller buffers may be fine. So when using small buffers, you should have an option in your software for the user to finetune the length used, for optimal performance. + Using this config option only affects the HMUSIC/HSTREAM channels that you create afterwards, not the ones that have already been created. So you can have channels with differing buffer lengths by using this config option each time before creating them. + If automatic updating is disabled, make sure you call frequently enough to keep the buffers updated. + + + + + The update period of HSTREAM and HMUSIC channel playback buffers. + period (int): The update period in milliseconds... 0 = disable automatic updating. The minimum period is 5ms, the maximum is 100ms. If the period specified is outside this range, it is automatically capped. + The update period is the amount of time between updates of the playback buffers of HSTREAM/HMUSIC channels. Shorter update periods allow smaller buffers to be set with the option, but as the rate of updates increases, so the overhead of setting up the updates becomes a greater part of the CPU usage. + The update period only affects HSTREAM and HMUSIC channels, it does not affect samples. Nor does it have any effect on decoding channels, as they are not played. + BASS creates one or more threads (determined by ) specifically to perform the updating, except when automatic updating is disabled (period=0) - then you must regularly call or instead. This allows you to synchronize BASS's CPU usage with your program's. For example, in a game loop you could call once per frame, which keeps all the processing in sync so that the frame rate is as smooth as possible. BASS_Update should be called at least around 8 times per second, even more often if the option is used to set smaller buffers. + The update period can be altered at any time, including during playback. The default period is 100ms. + + + + + Global sample volume. + volume (int): Sample global volume level... 0 (silent) - 10000 (full). + This config option allows you to have control over the volume levels of all the samples, which is useful for setup options (eg. separate music and fx volume controls). + A channel's final volume = channel volume * global volume / max volume. So, for example, if a stream channel's volume is 0.5 and the global stream volume is 8000, then effectively the stream's volume level is 0.4 (0.5 * 8000 / 10000 = 0.4). + + + + + Global stream volume. + volume (int): Stream global volume level... 0 (silent) - 10000 (full). + This config option allows you to have control over the volume levels of all streams, which is useful for setup options (eg. separate music and fx volume controls). + A channel's final volume = channel volume * global volume / max volume. So, for example, if a stream channel's volume is 0.5 and the global stream volume is 8000, then effectively the stream's volume level is 0.4 (0.5 * 8000 / 10000 = 0.4). + + + + + Global music volume. + volume (int): MOD music global volume level... 0 (silent) - 10000 (full). + This config option allows you to have control over the volume levels of all the MOD musics, which is useful for setup options (eg. separate music and fx volume controls). + A channel's final volume = channel volume * global volume / max volume. So, for example, if a stream channel's volume is 0.5 and the global stream volume is 8000, then effectively the stream's volume level is 0.4 (0.5 * 8000 / 10000 = 0.4). + + + + + Volume translation curve. + logvol (bool): Volume curve... = linear, = logarithmic. + DirectSound uses logarithmic volume and panning curves, which can be awkward to work with. + For example, with a logarithmic curve, the audible difference between 10000 and 9000, is not the same as between 9000 and 8000. + With a linear "curve" the audible difference is spread equally across the whole range of values, so in the previous example the audible difference between 10000 and 9000, and between 9000 and 8000 would be identical. + When using the linear curve, the volume range is from 0% (silent) to 100% (full). + When using the logarithmic curve, the volume range is from -100 dB (effectively silent) to 0 dB (full). For example, a volume level of 0.5 is 50% linear or -50 dB logarithmic. + The linear curve is used by default. + + + + + Panning translation curve. + logpan (bool): Panning curve... = linear, = logarithmic. + The panning curve affects panning in exactly the same way as the volume curve (BASS_CONFIG_CURVE_VOL) affects the volume. + The linear curve is used by default. + + + + + Pass 32-bit floating-point sample data to all DSP functions? + floatdsp (bool): If , 32-bit floating-point sample data is passed to all callback functions. + Normally DSP functions receive sample data in whatever format the channel is using, ie. it can be 8, 16 or 32-bit. But using this config option, BASS will convert 8/16-bit sample data to 32-bit floating-point before passing it to DSP functions, and then convert it back after all the DSP functions are done. As well as simplifying the DSP code (no need for 8/16-bit processing), this also means that there is no degradation of quality as sample data passes through a chain of DSP. + This config option also applies to effects set via , except for DX8 effects when using the "With FX flag" DX8 effect implementation. + Changing the setting while there are DSP or FX set could cause problems, so should be avoided. + Platform-specific: On Android and Windows CE, 8.24 bit fixed-point is used instead of floating-point. Floating-point DX8 effect processing requires DirectX 9 (or above) on Windows. + + + + + The 3D algorithm for software mixed 3D channels. + algo (int): Use one of the flags. + These algorithms only affect 3D channels that are being mixed in software. can be used to check whether a channel is being software mixed. + Changing the algorithm only affects subsequently created or loaded samples, musics, or streams; it does not affect any that already exist. + On Windows, DirectX 7 or above is required for this option to have effect. On other platforms, only the BASS_3DALG_DEFAULT and BASS_3DALG_OFF options are available. + + + + + Time to wait for a server to respond to a connection request. + timeout (int): The time to wait, in milliseconds. + The default timeout is 5 seconds (5000 milliseconds). + + + + + Internet download buffer length. + length (int): The buffer length, in milliseconds. + Increasing the buffer length decreases the chance of the stream stalling, but also increases the time taken by to create the stream, as it has to pre-buffer more data (adjustable via the option). Aside from the pre-buffering, this setting has no effect on streams without either the or flags. + When streaming in blocks, this option determines the download buffer length. The effective buffer length can actually be a bit more than that specified, including data that's been read from the buffer by the decoder but not been used yet. + This config option also determines the buffering used by "buffered" user file streams created with . + The default buffer length is 5 seconds (5000 milliseconds). The net buffer length should be larger than the length of the playback buffer (), otherwise the stream is likely to briefly stall soon after starting playback. + Using this config option only affects streams created afterwards, not any that have already been created. + + + + + Prevent channels being played when the output is paused? + noplay (bool): If , channels can't be played while the output is paused. + When the output is paused using , and this config option is enabled, channels can't be played until the output is resumed using . Attempts to play a channel will give a error. + By default, this config option is enabled. + + + + + Amount to pre-buffer when opening internet streams. + prebuf (int): Amount (percentage) to pre-buffer. + This setting determines what percentage of the buffer length () should be filled by . The default is 75%. Setting this lower (eg. 0) is useful if you want to display a "buffering progress" (using ) when opening internet streams, but note that this setting is just a minimum - BASS will always pre-download a certain amount to verify the stream. + As well as internet streams, this config setting also applies to "buffered" user file streams created with . + + + + + "User-Agent" header. + agent (string pointer): The "User-Agent" header. + BASS does not make a copy of the config string, so it must reside in the heap (not the stack), eg. a global variable. This also means that the agent setting can subsequently be changed at that location without having to call this function again. + Changes take effect from the next internet stream creation call. + + + + + Proxy server settings (in the form of "user:pass@server:port"... = don't use a proxy). + proxy (string pointer): The proxy server settings, in the form of "user:pass@server:port"... = don't use a proxy. "" (empty string) = use the OS's default proxy settings. If only the "user:pass@" part is specified, then those authorization credentials are used with the default proxy server. If only the "server:port" part is specified, then that proxy server is used without any authorization credentials. + BASS does not make a copy of the config string, so it must reside in the heap (not the stack), eg. a global variable. This also means that the proxy settings can subsequently be changed at that location without having to call this function again. + Changes take effect from the next internet stream creation call. + + + + + Use passive mode in FTP connections? + passive (bool): If , passive mode is used, otherwise normal/active mode is used. + Changes take effect from the next internet stream creation call. By default, passive mode is enabled. + + + + + The buffer length for recording channels. + length (int): The buffer length in milliseconds... 1000 (min) - 5000 (max). If the length specified is outside this range, it is automatically capped. + Unlike a playback buffer, where the aim is to keep the buffer full, a recording buffer is kept as empty as possible and so this setting has no effect on latency. The default recording buffer length is 2000 milliseconds. Unless processing of the recorded data could cause significant delays, or you want to use a large recording period with , there should be no need to increase this. + Using this config option only affects the recording channels that are created afterwards, not any that have already been created. So you can have channels with differing buffer lengths by using this config option each time before creating them. + + + + + Process URLs in PLS, M3U, WPL or ASX playlists? + netlists (int): When to process URLs in PLS, M3U, WPL or ASX playlists... 0 = never, 1 = in only, 2 = in and too. + When enabled, BASS will process PLS, M3U, WPL and ASX playlists, going through each entry until it finds a URL that it can play. + By default, playlist procesing is disabled. + + + + + The maximum number of virtual music channels (1-512) to use. + number (int): The maximum number of virtual music channels (1-512), ), which should be set before loading the IT file (doesn't affect already loaded files). + When there are no virtual channels free, the quietest one is killed to make way. That means any extra channels (due to raised limit) will be quieter ones. + Note that the virtual channel count/limit is in addition to the normal channels. + + + + + The amount of data to check in order to verify/detect the file format. + length (int): The amount of data to check, in bytes... 1000 (min) to 100000 (max). If the value specified is outside this range, it is automatically capped. + Of the file formats supported as standard, this setting only affects the detection of MP3/MP2/MP1 formats, + but it may also be used by add-ons (see the documentation). For internet (and "buffered" user file) streams, a quarter of the length is used, up to a minimum of 1000 bytes. + The verification length excludes any tags that may be at the start of the file. The default length is 16000 bytes. + + + + + The number of threads to use for updating playback buffers. + threads (int): The number of threads to use... 0 = disable automatic updating. + The number of update threads determines how many HSTREAM/HMUSIC channel playback buffers can be updated in parallel; + each thread can process one channel at a time. The default is to use a single thread, but additional threads can be used to take advantage of multiple CPU cores. + There is generally nothing much to be gained by creating more threads than there are CPU cores, but one benefit of using multiple threads even with a single CPU core is that a slow updating channel need not delay the updating of other channels. + When automatic updating is disabled (threads = 0), or should be used instead. + The number of update threads can be changed at any time, including during playback. + Platform-specific: The number of update threads is limited to 1 on the Android and Windows CE platforms. + + + + + Linux, Android and CE only: The output device buffer length. + length (int): The buffer length in milliseconds. + The device buffer is where the final mix of all playing channels is placed, ready for the device to play. Its length affects the latency of things like starting and stopping playback of a channel, so you will probably want to avoid setting it unnecessarily high, but setting it too short could result in breaks in the output. + When using a large device buffer, the attribute could be used to skip the channel buffering stage, to avoid further increasing latency for real-time generated sound and/or DSP/FX changes. + Changes to this config setting only affect subsequently initialized devices, not any that are already initialized. + This config option is only available on Linux, Android and Windows CE. The device's buffer is determined automatically on other platforms. + Platform-specific: On Linux, the driver may choose to use a different buffer length if it decides that the specified length is too short or long. The buffer length actually being used can be obtained with , like this: latency + minbuf / 2. + + + + + Use improved precision of position reporting on Vista/Win7 ? + precision (bool): Use the DSBCAPS_TRUEPLAYPOSITION option ? (default is ). + DirectSound offers a new DSBCAPS_TRUEPLAYPOSITION option under Vista/Win7 or above. This improves the precision of position reporting on Vista/Win7 (in a range within 10ms). + But it also appears to increase latency (around 20ms on Vista but less on Win7). The question now is which is more important: more precise position reporting or lower latency? + Set this option to to have BASS use the DSBCAPS_TRUEPLAYPOSITION option, and to not (default). + It also applies to the latency measuring (BASS_DEVICE_LATENCY), so you can see its effect there too; it should be set before the call in that case. + + + + + Supress silencing for corrupted MP3 frames. + errors (bool): Supress error correction silences? (default is ). + When BASS is detecting some corruption in an MP3 file's Huffman coding, it silences the frame to avoid any unpleasent noises that can result from corruption. + Set this parameter to in order to supress this behavior and + This applies only to the regular BASS version and NOT the "mp3-free" version. + + + + + Windows-only: Include a "Default" entry in the output device list? + default (bool): If , a 'Default' device will be included in the device list (default is ). + BASS does not usually include a "Default" entry in its device list, as that would ultimately map to one of the other devices and be a duplicate entry. When the default device is requested in a call (with device = -1), BASS will check the default device at that time, and initialize it. But Windows 7 has the ability to automatically switch the default output to the new default device whenever it changes, and in order for that to happen, the default device (rather than a specific device) needs to be used. That is where this option comes in. + When enabled, the "Default" device will also become the default device to (with device = -1). When the "Default" device is used, the and functions work a bit differently to usual; they deal with the "session" volume, which only affects the current process's output on the device, rather than the device's volume. + This option can only be set before or has been called. + Platform-specific: This config option is only available on Windows. It is available on all Windows versions (not including CE), but only Windows 7 has the default output switching feature. + + + + + The time to wait for a server to deliver more data for an internet stream. + timeout (int): The time to wait in milliseconds (default=0, infinite). + When the timeout is hit, the connection with the server will be closed. The default setting is 0, no timeout. + + + + + Enable speaker assignment with panning/balance control on Windows Vista and newer? + enable (bool): If , speaker assignment with panning/balance control is enabled on Windows Vista and newer. + Panning/balance control via the attribute is not available when speaker assignment is used on Windows due to the way that the speaker assignment needs to be implemented there. The situation is improved with Windows Vista, and speaker assignment can generally be done in a way that does permit panning/balance control to be used at the same time, but there may still be some drivers that it does not work properly with, so it is disabled by default and can be enabled via this config option. Changes only affect channels that are created afterwards, not any that already exist. + Platform-specific: This config option is only available on Windows. It is available on all Windows versions (not including CE), but only has effect on Windows Vista and newer. Speaker assignment with panning/balance control is always possible on other platforms, where BASS generates the final mix. + + + + + Gets the total number of HSTREAM/HSAMPLE/HMUSIC/HRECORD handles. + none: only used with . + The handle count may not only include the app-created stuff but also internal stuff, eg. BASS_WASAPI_Init will create a stream when the BASS_WASAPI_BUFFER flag is used. + + + + + Gets or Sets the Unicode character set in device information. + utf8 (bool): If , device information will be in UTF-8 form. Otherwise it will be ANSI. + This config option determines what character set is used in the structure. + The default setting is UNICODE for Bass.Net and should NOT be changed! It might only be changed before or or or has been called. + Platform-specific: This config option is only available on Windows. + + + + + Gets or Sets the default sample rate conversion quality. + quality (int): The sample rate conversion quality... 0 = linear interpolation, 1 = 8 point sinc interpolation, 2 = 16 point sinc interpolation, 3 = 32 point sinc interpolation. Other values are also accepted. + This config option determines what sample rate conversion quality new channels will initially have, except for sample channels (HCHANNEL), which use the BASS_CONFIG_SRC_SAMPLE setting. + A channel's sample rate conversion quality can subsequently be changed via the BASS_ATTRIB_SRC attribute (see ). + The default setting is 1 (8 point sinc interpolation). + + + + + Gets or Sets the default sample rate conversion quality for samples. + quality (int): The sample rate conversion quality... 0 = linear interpolation, 1 = 8 point sinc interpolation, 2 = 16 point sinc interpolation, 3 = 32 point sinc interpolation. Other values are also accepted. + This config option determines what sample rate conversion quality a new sample channel will initially have, following a call. + The channel's sample rate conversion quality can subsequently be changed via the BASS_ATTRIB_SRC attribute (see ). + The default setting is 0 (linear interpolation). + + + + + BASS_AC3 add-on: dynamic range compression option + dynrng (bool): If dynamic range compression is enbaled (default is ). + + + + + BASSWMA add-on: Prebuffer internet streams on creation, before returning from BASS_WMA_StreamCreateFile? + prebuf (bool): The Windows Media modules must prebuffer a stream before starting decoding/playback of it. This option determines when/where to wait for that to be completed. + The Windows Media modules must prebuffer a stream before starting decoding/playback of it. + This option determines whether the stream creation function (eg. ) will wait for the prebuffering to complete before returning. + If playback of a stream is attempted before it has prebuffered, it will stall and then resume once it has finished prebuffering. + The prebuffering progress can be monitored via (BASS_FILEPOS_WMA_BUFFER). + This option is enabled by default. + + + + + BASSWMA add-on: use BASS file handling. + bassfile (bool): Default is disabled (). + When enabled () BASSWMA uses BASS's file routines when playing local files. It uses the IStream interface to do that. + This would also allow to support the "offset" parameter for WMA files with . + The downside of enabling this feature is, that it stops playback while encoding from working. + + + + + BASSWMA add-on: enable network seeking? + seek (bool): If seeking in network files/streams is enabled (default is ). + If , it allows seeking before the entire file has been downloaded/cached. Seeking is slow that way, so it's disabled by default. + + + + + BASSWMA add-on: play audio from WMV (video) files? + playwmv (bool): If (default) BASSWMA will play the audio from WMV video files. If WMV files will not be played. + + + + + BASSWMA add-on: use a seperate thread to decode the data? + async (bool): If BASSWMA will decode the data in a seperate thread. If (default) the normal file system will be used. + + The WM decoder can by synchronous (decodes data on demand) or asynchronous (decodes in the background). + With the background decoding, BASSWMA buffers the data that it receives from the decoder for the STREAMPROC to access. + The start of playback/seeking may well be slightly delayed due to there being no data available immediately. + Internet streams are only supported by the asynchronous system, but local files can use either, and BASSWMA uses the synchronous system by default. + + + + + + BASSCD add-on: Automatically free an existing stream when creating a new one on the same drive? + freeold (bool): Only one stream can exist at a time per CD drive. So if a stream using the same drive already exists, stream creation function calls will fail, unless this config option is enabled to automatically free the existing stream. This is enabled by default. + + + + + BASSCD add-on: Number of times to retry after a read error. + retries (int): Number of times to retry reading...0 = don't retry. The default is 2 retries. + + + + + BASSCD add-on: Automatically reduce the read speed when a read error occurs? + autospd (bool): By default, this option is disabled. + If , the read speed will be halved when a read error occurs, before retrying (if the BASS_CONFIG_CD_RETRY config setting allows). + + + + + BASSCD add-on: Skip past read errors? + skip (bool): If , reading will skip onto the next frame when a read error occurs, otherwise reading will stop. + When skipping an error, it will be replaced with silence, so that the track length is unaffected. Before skipping past an error, BASSCD will first retry according to the setting. + + + + + BASSCD add-on: The server to use in CDDB requests. + server (string): The CDDB server address, in the form of "user:pass@server:port/path". The "user:pass@", ":port" and "/path" parts are optional; only the "server" part is required. If not provided, the port and path default to 80 and "/~cddb/cddb.cgi", respectively. + A copy is made of the provided server string, so it need not persist beyond the call. The default setting is "freedb.freedb.org". . + The proxy server, as configured via the BASS_CONFIG_NET_PROXY option, is used when connecting to the CDDB server. + + + + + BASSenc add-on: Encoder DSP priority (default -1000) + priority (int): The priorty determines where in the DSP chain the encoding is performed - all DSP with a higher priority will be present in the encoding. Changes only affect subsequent encodings, not those that have already been started. The default priority is -1000. + + + + + BASSenc add-on: The maximum queue length (default 10000, 0=no limit) + limit (int): The async encoder queue size limit in milliseconds; 0=unlimited. + When queued encoding is enabled, the queue's buffer will grow as needed to hold the queued data, up to a limit specified by this config option. + The default limit is 10 seconds (10000 milliseconds). Changes only apply to new encoders, not any already existing encoders. + + + + + BASSenc add-on: The time to wait to send data to a cast server (default 5000ms) + timeout (int): The time to wait, in milliseconds. + When an attempt to send data is timed-out, the data is discarded. can be used to receive a notification of when this happens. + The default timeout is 5 seconds (5000 milliseconds). Changes take immediate effect. + + + + + BASSenc add-on: Proxy server settings when connecting to Icecast and Shoutcast (in the form of "[user:pass@]server:port"... = don't use a proxy but a direct connection). + proxy (string pointer): The proxy server settings, in the form of "[user:pass@]server:port"... = don't use a proxy but make a direct connection (default). If only the "server:port" part is specified, then that proxy server is used without any authorization credentials. + BASSenc does not make a copy of the config string, so it must reside in the heap (not the stack), eg. a global variable. This also means that the proxy settings can subsequently be changed at that location without having to call this function again. + Changes take effect from the next internet stream creation call. By default, BASSenc will not use any proxy settings when connecting to Icecast and Shoutcast. + + + + + BASSMIDI add-on: Automatically compact all soundfonts following a configuration change? + compact (bool): If , all soundfonts are compacted following a MIDI stream being freed, or a call. + The compacting isn't performed immediately upon a MIDI stream being freed or being called. It's actually done 2 seconds later (in another thread), so that if another MIDI stream starts using the soundfonts in the meantime, they aren't needlessly closed and reopened. + Samples that have been preloaded by are not affected by automatic compacting. Other samples that have been preloaded by are affected though, so it is probably wise to disable this option when using that function. + By default, this option is enabled. + + + + + BASSMIDI add-on: The maximum number of samples to play at a time (polyphony). + voices (int): Maximum number of samples to play at a time... 1 (min) - 256 (max). + This setting determines the maximum number of samples that can play together in a single MIDI stream. This isn't necessarily the same thing as the maximum number of notes, due to presets often layering multiple samples. When there are no voices available to play a new sample, the voice with the lowest volume will be killed to make way for it. + The more voices that are used, the more CPU that is required. So this option can be used to restrict that, for example on a less powerful system. The CPU usage of a MIDI stream can also be restricted via the attribute. + Changing this setting only affects subsequently created MIDI streams, not any that have already been created. The default setting is 128 voices. + Platform-specific + The default setting is 100, except on iOS, where it is 30. + + + + + BASSMIDI add-on: Automatically load matching soundfonts? + autofont (bool): If , BASSMIDI will try to load a soundfont matching the MIDI file. + This option only applies to local MIDI files, loaded using (or via the plugin system). BASSMIDI won't look for matching soundfonts for MIDI files loaded from the internet. + By default, this option is enabled. + + + + + BASSMIDI add-on: Default soundfont usage + filename (string): Filename of the default soundfont to use ( = no default soundfont). + When setting the default soundfont, a copy is made of the filename, so it does not need to persist beyond the call. If the specified soundfont cannot be loaded, the default soundfont setting will remain as it is. can be used to confirm what that is. + On Windows, the default is to use one of the Creative soundfonts (28MBGM.SF2 or CT8MGM.SF2 or CT4MGM.SF2 or CT2MGM.SF2), if present in the windows system directory. + + + + + BASSmix add-on: The order of filter used to reduce aliasing (only available/used pre BASSmix 2.4.7, where BASS_CONFIG_SRC is used). + order (int): The filter order... 2 (min) to 50 (max), and even. If the value specified is outside this range, it is automatically capped. + The filter order determines how abruptly the level drops at the cutoff frequency, or the roll-off. The levels rolls off at 6 dB per octave for each order. For example, a 4th order filter will roll-off at 24 dB per octave. A low order filter may result in some aliasing persisting, and sounds close to the cutoff frequency being attenuated. + Higher orders reduce those things, but require more processing. + By default, a 4th order filter is used. Changes only affect channels that are subsequently plugged into a mixer, not those that are already plugged in. + + + + + BASSmix add-on: The source channel buffer size multiplier. + multiple (int): The buffer size multiplier... 1 (min) to 5 (max). If the value specified is outside this range, it is automatically capped. + When a source channel has buffering enabled, the mixer will buffer the decoded data, so that it is available to the and functions. + To reach the source channel's buffer size, the multiplier (multiple) is applied to the BASS_CONFIG_BUFFER setting at the time of the mixer's creation. If the source is played at it's default rate, then the buffer only need to be as big as the mixer's buffer. + But if it's played at a faster rate, then the buffer needs to be bigger for it to contain the data that is currently being heard from the mixer. For example, playing a channel at 2x its normal speed would require the buffer to be 2x the normal size (multiple = 2). + Larger buffers obviously require more memory, so the multiplier should not be set higher than necessary. + The default multiplier is 2x. Changes only affect subsequently setup channel buffers. An existing channel can have its buffer reinitilized by disabling and then re-enabling the BASS_MIXER_BUFFER flag using . + + + + + BASSmix add-on: How far back to keep record of source positions to make available for . + length (int): The length of time to back, in milliseconds. + If a mixer is not a decoding channel (not using the flag), this config setting will just be a minimum and the mixer will always have a position record at least equal to its playback buffer length, as determined by the config option. + The default setting is 2000ms. Changes only affect newly created mixers, not any that already exist. + + + + + BASSmix add-on: The splitter buffer length. + length (int): The buffer length in milliseconds... 100 (min) to 5000 (max). If the value specified is outside this range, it is automatically capped. + When a source has its first splitter stream created, a buffer is allocated for its sample data, which all of its subsequently created splitter streams will share. This config option determines how big that buffer is. The default is 2000ms. + The buffer will always be kept as empty as possible, so its size does not necessarily affect latency; it just determines how far splitter streams can drift apart before there are buffer overflow issues for those left behind. + Changes do not affect buffers that have already been allocated; any sources that have already had splitter streams created will continue to use their existing buffers. + + + + + BASSaac add-on: play audio from mp4 (video) files? + playmp4 (bool): If (default) BASSaac will play the audio from mp4 video files. If mp4 video files will not be played. + + + + + BASSaac add-on: Support MP4 in BASS_AAC_StreamCreateXXX functions? + usemp4 (bool): If BASSaac supports MP4 in the BASS_AAC_StreamCreateXXX functions. If (default) only AAC is supported. + + + + + BASSWinamp add-on: Winamp input timeout. + timeout (int): The time (in milliseconds) to wait until timing out, because the plugin is not using the output system. + + + + + BASS_DEVICEINFO flags to be used with + + + + + The device is not enabled and not initialized. + + + + + The device is enabled. It will not be possible to initialize the device if this flag is not present. + + + + + The device is the system default. + + + + + The device is initialized, ie. or has been called. + + + + + BASS_INFO flags to be used with + + + + + Non of the falgs are set + + + + + The device supports all sample rates between minrate and maxrate. + + + + + The device's drivers do NOT have DirectSound support, so it is being emulated. Updated drivers should be installed. + + + + + The device driver has been certified by Microsoft. This flag is always set on WDM drivers. + + + + + Mono samples are supported by hardware mixing. + + + + + Stereo samples are supported by hardware mixing. + + + + + 8-bit samples are supported by hardware mixing. + + + + + 16-bit samples are supported by hardware mixing. + + + + + BASS_RECORDINFO flags to be used with + + + + + Non of the flags is set + + + + + The device's drivers do NOT have DirectSound support, so it is being emulated. Updated drivers should be installed. + + + + + The device driver has been certified by Microsoft. This flag is always set on WDM drivers. + + + + + Formats field of BASS_RECORDINFO to be used with + + + + + unknown format + + + + + 11.025 kHz, Mono, 8-bit + + + + + 11.025 kHz, Stereo, 8-bit + + + + + 11.025 kHz, Mono, 16-bit + + + + + 11.025 kHz, Stereo, 16-bit + + + + + 22.05 kHz, Mono, 8-bit + + + + + 22.05 kHz, Stereo, 8-bit + + + + + 22.05 kHz, Mono, 16-bit + + + + + 22.05 kHz, Stereo, 16-bit + + + + + 44.1 kHz, Mono, 8-bit + + + + + 44.1 kHz, Stereo, 8-bit + + + + + 44.1 kHz, Mono, 16-bit + + + + + 44.1 kHz, Stereo, 16-bit + + + + + 48 kHz, Mono, 8-bit + + + + + 48 kHz, Stereo, 8-bit + + + + + 48 kHz, Mono, 16-bit + + + + + 48 kHz, Stereo, 16-bit + + + + + 96 kHz, Mono, 8-bit + + + + + 96 kHz, Stereo, 8-bit + + + + + 96 kHz, Mono, 16-bit + + + + + 96 kHz, Stereo, 16-bit + + + + + 3D Channel Mode flags to be used with e.g. + + + + + To be used with in order to leave the current 3D processing mode unchanged. + + + + + normal 3D processing + + + + + The channel's 3D position (position/velocity/orientation) are relative to the listener. + When the listener's position/velocity/orientation is changed with , the channel's position relative to the listener does not change. + + + + + Turn off 3D processing on the channel, the sound will be played in the center. + + + + + Channel Position Mode flags to be used with e.g. , , or . + + + + + Byte position. + + + + + Order.Row position (HMUSIC only). + + + + + Tick position (MIDI streams only). + + + + + MOD Music Flag: Stop all notes when moving position. + + + + + MOD Music Flag: Stop all notes and reset bmp/etc when moving position. + + + + + Mixer Flag: Don't ramp-in the start after seeking. + + + + + Get the decoding (not playing) position. + + + + + Flag: decode to the position instead of seeking. + + + + + Midi Add-On: Let the old sound decay naturally (including reverb) when changing the position, including looping and such can also be used in calls to have it apply to particular position changes. + + + + + Software 3D mixing algorithm modes to be used with using the BASS_CONFIG_3DALGORITHM. + + + + + Default algorithm (currently translates to BASS_3DALG_OFF) + + + + + Uses normal left and right panning. The vertical axis is ignored except for scaling of volume due to distance. + Doppler shift and volume scaling are still applied, but the 3D filtering is not performed. + This is the most CPU efficient software implementation, but provides no virtual 3D audio effect. + Head Related Transfer Function processing will not be done. + Since only normal stereo panning is used, a channel using this algorithm may be accelerated by a 2D hardware voice if no free 3D hardware voices are available. + + + + + This algorithm gives the highest quality 3D audio effect, but uses more CPU. + Requires Windows 98 2nd Edition or Windows 2000 that uses WDM drivers, if this mode is not available then BASS_3DALG_OFF will be used instead. + + + + + This algorithm gives a good 3D audio effect, and uses less CPU than the FULL mode. + Requires Windows 98 2nd Edition or Windows 2000 that uses WDM drivers, if this mode is not available then BASS_3DALG_OFF will be used instead. + + + + + STREAMPROC flag used with resp. used with a user sample stream to be used with . + + + + + Create a "dummy" stream. + A dummy stream doesn't have any sample data of its own, but a decoding dummy stream (with BASS_STREAM_DECODE flag) can be used to apply DSP/FX processing to any sample data, + by setting DSP/FX on the stream and feeding the data through . + The dummy stream should have the same sample format as the data being fed through it. + + + + + Create a "push" stream. + Instead of BASS pulling data from a STREAMPROC function, data is pushed to BASS via . + + + + + Flag to signify that the end of the stream is reached. + + + + + User file system flag to be used with + + + + + Unbuffered file system (like also used by ). + The unbuffered file system is what is used by . In this system, BASS does not do any intermediate buffering - + it simply requests data from the file as and when it needs it. This means that reading () must be quick, + otherwise the decoding will be delayed and playback buffer underruns (old data repeated) are a possibility. + It's not so important for seeking () to be fast, as that is generally not required during decoding, except when looping a file. + + + + + Buffered file system (like also used by ). + The buffered file system is what is used by . + As the name suggests, data from the file is buffered so that it's readily available for decoding - + BASS creates a thread dedicated to "downloading" the data. This is ideal for when the data is coming from a source that has high latency, like the internet. + It's not possible to seek in buffered file streams, until the download has reached the requested position - it's not possible to seek at all if it's being streamed in blocks. + + + + + Buffered, with the data pushed to BASS via . + The push buffered file system is the same as STREAMFILE_BUFFER, except that instead of the file data being pulled from the function in a "download" thread, + the data is pushed to BASS via . A function is still required, to get the initial data used in the creation of the stream. + + + + + Stream File Position modes to be used with + + + + + Position that is to be decoded for playback next. This will be a bit ahead of the position actually being heard due to buffering. + + + + + Download progress of an internet file stream or "buffered" user file stream. + + + + + End of the file, in other words the file length. When streaming in blocks, the file length is unknown, so the download buffer length is returned instead. + + + + + Start of stream data in the file. + + + + + Internet file stream or "buffered" user file stream is still connected? 0 = no, 1 = yes. + + + + + The amount of data in the buffer of an internet file stream or "buffered" user file stream. + Unless streaming in blocks, this is the same as BASS_FILEPOS_DOWNLOAD. + + + + + WMA add-on: internet buffering progress (0-100%) + + + + + Voice allocation management flags. + These flags enable hardware resource stealing... if the hardware has no available voices, a currently playing buffer will be stopped to make room for the new buffer. + + + NOTE: only samples loaded/created with the BASS_SAMPLE_VAM flag are considered for termination by the DX7 voice management. + + + + + Play the sample in hardware. If no hardware voices are available then the "play" call will fail + + + + + Play the sample in software (ie. non-accelerated). No other VAM flags may be used together with this flag. + + + + + If there are no free hardware voices, the buffer to be terminated will be the one with the least time left to play. + + + + + If there are no free hardware voices, the buffer to be terminated will be one that was loaded/created with the BASS_SAMPLE_MUTEMAX flag and is beyond it's max distance. + If there are no buffers that match this criteria, then the "play" call will fail. + + + + + If there are no free hardware voices, the buffer to be terminated will be the one with the lowest priority. + + + + + Stream/Sample/Music/Recording/BASS_FX create flags to be used with , , + , , , , , + , and + , , , etc. + + + + + 0 = default create stream: 16 Bit, stereo, no Float, hardware mixing, no Loop, no 3D, no speaker assignments... + + + + + Use 8-bit resolution. If neither this or the BASS_SAMPLE_FLOAT flags are specified, then the stream is 16-bit. + + + + + Decode/play the stream (MP3/MP2/MP1 only) in mono, reducing the CPU usage (if it was originally stereo). + This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + + + + + Loop the file. This flag can be toggled at any time using . + + + + + Use 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . + 3D streams must be mono (chans=1). The SPEAKER flags can not be used together with this flag. + + + + + Force the stream to not use hardware mixing. + + + + + Sample: muted at max distance (3D only) + + + + + Sample: uses the DX7 voice allocation & management + + + + + Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. + Use to add effects to the stream. Requires DirectX 8 or above. + + + + + Use 32-bit floating-point sample data (see Floating-Point Channels for details). WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag. + + + + + Recording: Start the recording paused. Use to start it. + + + + + Enable pin-point accurate seeking (to the exact byte) on the MP3/MP2/MP1 stream. + This also increases the time taken to create the stream, due to the entire file being pre-scanned for the seek points. + Note: BASS_STREAM_PRESCAN is ONLY needed for files with a VBR, files with a CBR are always accurate. + + + + + Automatically free the stream's resources when it has reached the end, or when (or ) is called. + + + + + Restrict the download rate of the file to the rate required to sustain playback. + If this flag is not used, then the file will be downloaded as quickly as possible. + This flag has no effect on "unbuffered" streams (buffer=). + + + + + Download and play the file in smaller chunks. + Uses a lot less memory than otherwise, but it's not possible to seek or loop the stream - once it's ended, the file must be opened again to play it again. + This flag will automatically be applied when the file length is unknown. + This flag also has the effect of resticting the download rate. + This flag has no effect on "unbuffered" streams (buffer=). + + + + + Decode the sample data, without outputting it. Use to retrieve decoded sample data. + BASS_SAMPLE_SOFTWARE/3D/FX/AUTOFREE are all ignored when using this flag, as are the SPEAKER flags. + + + + + Pass status info (HTTP/ICY tags) from the server to the DOWNLOADPROC callback during connection. + This can be useful to determine the reason for a failure. + + + + + Front speakers (channel 1/2) + + + + + Rear/Side speakers (channel 3/4) + + + + + Center & LFE speakers (5.1, channel 5/6) + + + + + Rear Center speakers (7.1, channel 7/8) + + + + + Speaker Modifier: left channel only + + + + + Speaker Modifier: right channel only + + + + + Front Left speaker only (channel 1) + + + + + Front Right speaker only (channel 2) + + + + + Rear/Side Left speaker only (channel 3) + + + + + Rear/Side Right speaker only (channel 4) + + + + + Center speaker only (5.1, channel 5) + + + + + LFE speaker only (5.1, channel 6) + + + + + Rear Center Left speaker only (7.1, channel 7) + + + + + Rear Center Right speaker only (7.1, channel 8) + + + + + speakers Pair 1 + + + + + speakers Pair 2 + + + + + speakers Pair 3 + + + + + speakers Pair 4 + + + + + speakers Pair 5 + + + + + Speakers Pair 6 + + + + + Speakers Pair 7 + + + + + Speakers Pair 8 + + + + + Speakers Pair 9 + + + + + Speakers Pair 10 + + + + + Speakers Pair 11 + + + + + Speakers Pair 12 + + + + + Speakers Pair 13 + + + + + Speakers Pair 14 + + + + + Speakers Pair 15 + + + + + File is a Unicode (16-bit characters) filename + + + + + Sample: override lowest volume + + + + + Sample: override longest playing + + + + + Sample: override furthest from listener (3D only) + + + + + BASSWV add-on: limit to stereo + + + + + BASS_AC3 add-on: downmix to stereo + + + + + BASS_AC3 add-on: downmix to quad + + + + + BASS_AC3 add-on: downmix to dolby + + + + + BASS_AC3 add-on: enable dynamic range compression + + + + + BASS_AAC add-on: downmatrix to stereo + + + + + BASSmix add-on: end the stream when there are no sources + + + + + BASSmix add-on: don't process the source + + + + + BASSmix add-on: don't stall when there are no sources + + + + + BASSmix add-on: resume a stalled mixer immediately upon new/unpaused source + + + + + BASSmix add-on: enable support. + + + + + BASSmix add-on: Limit mixer processing to the amount available from this source. + + + + + BASSmix add-on: Matrix mixing + + + + + BASSmix add-on: downmix to stereo (or mono if mixer is mono) + + + + + BASSmix add-on: don't ramp-in the start + + + + + BASSmix add-on: filter the sample data when resampling (only available/used in pre BASSmix v2.4.7). + + + + + BASSmix add-on: only read buffered data. + + + + + BASSmix add-on: buffer source data for and . + + + + + BASSCD add-on: Read sub-channel data. 96 bytes of de-interleaved sub-channel data will be returned after each 2352 bytes of audio. This flag can not be used with the BASS_SAMPLE_FLOAT flag, and is ignored if the BASS_STREAM_DECODE flag is not used. + + + + + BASSCD add-on: Read sub-channel data, without using any hardware de-interleaving. This is identical to the BASS_CD_SUBCHANNEL flag, except that the de-interleaving is always performed by BASSCD even if the drive is apparently capable of de-interleaving itself. + + + + + BASSCD add-on: Include C2 error info. 296 bytes of C2 error info is returned after each 2352 bytes of audio (and optionally 96 bytes of sub-channel data). + This flag cannot be used with the BASS_SAMPLE_FLOAT flag, and is ignored if the BASS_STREAM_DECODE flag is not used. + The first 294 bytes contain the C2 error bits (one bit for each byte of audio), followed by a byte containing the logical OR of all 294 bytes, + which can be used to quickly check if there were any C2 errors. The final byte is just padding. + Note that if you request both sub-channel data and C2 error info, the C2 info will come before the sub-channel data! + + + + + BASSMIDI add-on: Let the sound decay naturally (including reverb) instead of stopping it abruptly at the end of the file. This flag can be toggled at any time using . + + + + + BASSMIDI add-on: Disable the MIDI reverb/chorus processing. This flag can be toggled at any time using . + + + + + BASSMIDI add-on: Let the old sound decay naturally (including reverb) when changing the position, including looping. This flag can be toggled at any time using , and can also be used in calls to have it apply to particular position changes. + + + + + BASS_FX add-on: Free the source handle as well? + + + + + BASS_FX add-on: If in use, then you can do other stuff while detection's in process. + + + + + BASS_FX add-on: If in use, then will auto multiply bpm by 2 (if BPM < MinBPM*2) + + + + + Music: Use 32-bit floating-point sample data (see Floating-Point Channels for details). WDM drivers or the BASS_STREAM_DECODE flag are required to use this flag. + + + + + Music: Decode/play the mod music in mono, reducing the CPU usage (if it was originally stereo). + This flag is automatically applied if BASS_DEVICE_MONO was specified when calling . + + + + + Music: Loop the music. This flag can be toggled at any time using . + + + + + Music: Use 3D functionality. This is ignored if BASS_DEVICE_3D wasn't specified when calling . + 3D streams must be mono (chans=1). The SPEAKER flags can not be used together with this flag. + + + + + Music: Enable the old implementation of DirectX 8 effects. See the DX8 effect implementations section for details. + Use to add effects to the stream. Requires DirectX 8 or above. + + + + + Music: Automatically free the music when it ends. This allows you to play a music and forget about it, as BASS will automatically free the music's resources when it has reached the end or when (or ) is called. + Note that some musics never actually end on their own (ie. without you stopping them). + + + + + Music: Decode the music into sample data, without outputting it. + Use to retrieve decoded sample data. + BASS_SAMPLE_SOFTWARE/3D/FX/AUTOFREE are ignored when using this flag, as are the SPEAKER flags. + + + + + Music: Calculate the playback length of the music, and enable seeking in bytes. This slightly increases the time taken to load the music, depending on how long it is. + In the case of musics that loop, the length until the loop occurs is calculated. Use to retrieve the length. + + + + + Music: Use "normal" ramping (as used in FastTracker 2). + + + + + Music: Use "sensitive" ramping. + + + + + Music: Apply XMPlay's surround sound to the music (ignored in mono). + + + + + Music: Apply XMPlay's surround sound mode 2 to the music (ignored in mono). + + + + + Music: Play .MOD file as FastTracker 2 would. + + + + + Music: Play .MOD file as ProTracker 1 would. + + + + + Music: Use non-interpolated mixing. This generally reduces the sound quality, but can be good for chip-tunes. + + + + + Music: Sinc interpolated sample mixing. + This increases the sound quality, but also requires quite a bit more processing. If neither this or the BASS_MUSIC_NONINTER flag is specified, linear interpolation is used. + + + + + Music: Stop all notes when seeking (using ). + + + + + Music: Stop all notes and reset bpm/etc when seeking. + + + + + Music: Stop the music when a backward jump effect is played. This stops musics that never reach the end from going into endless loops. + Some MOD musics are designed to jump all over the place, so this flag would cause those to be stopped prematurely. + If this flag is used together with the BASS_SAMPLE_LOOP flag, then the music would not be stopped but any BASS_SYNC_END sync would be triggered. + + + + + Music: Don't load the samples. This reduces the time taken to load the music, notably with MO3 files, which is useful if you just want to get the name and length of the music without playing it. + + + + + DSHOW add-on: Use this flag to enable mixing video on a channel. + + + + + DSHOW add-on: Use this flag to disable audio processing. + + + + + DSHOW add-on: Use this flag to enable auto dvd functions(on mouse down, keys etc). + + + + + DSHOW add-on: Use this flag to restart the stream when it's finished. + + + + + DSHOW add-on: Use this to enable video processing. + + + + + Channel Type flags to be used with (see also ) + + + + + Unknown channel format. + + + + + Sample channel. (HCHANNEL) + + + + + Recording channel. (HRECORD) + + + + + MO3 format music. + + + + + User sample stream. This can also be used as a flag to test if the channel is any kind of HSTREAM. + + + + + OGG format stream. + + + + + MP1 format stream. + + + + + MP2 format stream. + + + + + MP2 format stream. + + + + + WAV format stream. + + + + + CoreAudio codec stream. Additional information is avaliable via the tag. + + + + + Media Foundation codec stream. Additional information is avaliable via the tag. + + + + + BASSmix mixer stream. + + + + + BASSmix splitter stream. + + + + + WAV format stream, LOWORD=codec. + + + + + WAV format stream, PCM 16-bit. + + + + + WAV format stream, FLOAT 32-bit. + + + + + MOD format music. This can also be used as a flag to test if the channel is any kind of HMUSIC. + + + + + MTM format music. + + + + + S3M format music. + + + + + XM format music. + + + + + IT format music. + + + + + WavPack Lossless format stream. + + + + + WavPack Hybrid Lossless format stream. + + + + + WavPack Lossy format stream. + + + + + WavPack Hybrid Lossy format stream. + + + + + Audio-CD, CDA + + + + + WMA format stream. + + + + + MP3 over WMA format stream. + + + + + FLAC format stream. + + + + + FLAC OGG format stream. + + + + + Optimfrog format stream. + + + + + APE format stream. + + + + + MPC format stream. + + + + + AAC format stream. + + + + + MP4 format stream. + + + + + Speex format stream. + + + + + Apple Lossless (ALAC) format stream. + + + + + TTA format stream. + + + + + AC3 format stream. + + + + + Winamp input format stream. + + + + + MIDI sound format stream. + + + + + ADX format stream. + ADX is a lossy proprietary audio storage and compression format developed by CRI Middleware specifically for use in video games, it is derived from ADPCM. + + + + + AIX format stream. + Only for ADX of all versions (with AIXP support). + + + + + Video format stream. + + + + + EAX environment constants to be used with (int) + + + + + -1 = leave current EAX environment as is + + + + + Generic + + + + + Padded Cell + + + + + Room + + + + + Bathroom + + + + + Livingroom + + + + + Stoneroom + + + + + Auditorium + + + + + Concert Hall + + + + + Cave + + + + + Arena + + + + + Hangar + + + + + Carpeted Hallway + + + + + Hallway + + + + + Stone Corridor + + + + + Alley + + + + + Forest + + + + + City + + + + + Mountains + + + + + Quarry + + + + + Plain + + + + + Parkinglot + + + + + Sewer Pipe + + + + + Underwater + + + + + Drugged + + + + + Dizzy + + + + + Psychotic + + + + + total number of environments + + + + + EAX environment preset constants to be used with (int) + + + + + Generic + + + + + Preset Padded Cell + + + + + Preset Room + + + + + Preset Bathroom + + + + + Preset Livingroom + + + + + Preset Stoneroom + + + + + Preset Auditorium + + + + + Preset Concert Hall + + + + + Preset Cave + + + + + Preset Arena + + + + + Preset Hangar + + + + + Preset Carpeted Hallway + + + + + Preset Hallway + + + + + Preset Stone Corridor + + + + + Preset Alley + + + + + Preset Forest + + + + + Preset City + + + + + Preset Mountains + + + + + Preset Quarry + + + + + Preset Plain + + + + + Preset Parkinglot + + + + + Preset Sewer Pipe + + + + + Preset Underwater + + + + + Preset Drugged + + + + + Preset Dizzy + + + + + Preset Psychotic + + + + + Flags to be used with . + + + + + Query how much data is buffered + + + + + FFT flag: FFT for each channel, else all combined + + + + + FFT flag: no Hanning window + + + + + FFT flag: pre-remove DC bias + + + + + flag: return floating-point sample data + + + + + 256 sample FFT (returns 128 floating-point values) + + + + + 512 sample FFT (returns 256 floating-point values) + + + + + 1024 sample FFT (returns 512 floating-point values) + + + + + 2048 sample FFT (returns 1024 floating-point values) + + + + + 4096 sample FFT (returns 2048 floating-point values) + + + + + 8192 sample FFT (returns 4096 floating-point values) + + + + + 16384 sample FFT (returns 8192 floating-point values) + + + + + return values. + + + + + The channel is not active, or handle is not a valid channel. + + + + + The channel is playing (or recording). + + + + + Playback of the stream has been stalled due to there not being enough sample data to continue playing. The playback will automatically resume once there's sufficient data to do so. + + + + + The channel is paused. + + + + + flags. + + + + + No input flag change. + + + + + Disable the input. This flag can't be used when the device supports only one input at a time. + + + + + Enable the input. If the device only allows one input at a time, then any previously enabled input will be disabled by this. + + + + + flags. + + + + + The type of input is errorness. + + + + + The type of input is also indicated in the high 8-bits of (use BASS_INPUT_TYPE_MASK to test the return value). + + + + + Anything that is not covered by the other types + + + + + Digital input source, for example, a DAT or audio CD. + + + + + Line-in. On some devices, "Line-in" may be combined with other analog sources into a single BASS_INPUT_TYPE_ANALOG input. + + + + + Microphone. + + + + + Internal MIDI synthesizer. + + + + + Analog audio CD. + + + + + Telephone. + + + + + PC speaker. + + + + + The device's WAVE/PCM output. + + + + + Auxiliary. Like "Line-in", "Aux" may be combined with other analog sources into a single BASS_INPUT_TYPE_ANALOG input on some devices. + + + + + Analog, typically a mix of all analog sources (what you hear). + + + + + Types of what's returned by . + + + + + ID3v1 tags : A pointer to a 128 byte block is returned (see ). + See www.id3.org for details of the block's structure. + + + + + ID3v2 tags : A pointer to a variable length block is returned. + See www.id3.org for details of the block's structure. + + + + + OGG comments : Only available when streaming an OGG file. A pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. + + + + + HTTP headers : Only available when streaming from a HTTP server. A pointer to a series of null-terminated ANSI strings is returned, the final string ending with a double null. + + + + + ICY headers : A pointer to a series of null-terminated ANSI strings is returned, the final string ending with a double null. + + + + + ICY (Shoutcast) metadata : A single null-terminated ANSI string containing the current stream title and url (usually omitted). The format of the string is: StreamTitle='xxx';StreamUrl='xxx'; + + + + + APE (v1 or v2) tags : Only available when streaming an APE file. A pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. + + + + + iTunes/MP4 metadata : Only available when streaming a MP4 file. A pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. + + + + + WMA header tags: WMA tags : Only available when streaming a WMA file. A pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. + + + + + OGG encoder : A single null-terminated UTF-8 string. + + + + + Lyric3v2 tag : A single ANSI string is returned, containing the Lyrics3v2 information. See www.id3.org/Lyrics3v2 for details of its format. + + + + + WMA mid-stream tag: a single UTF-8 string. + + + + + Apple CoreAudio codec info : structure. + + + + + FLAC cuesheet : structure (which includes and ). + + + + + WMA codec: A description of the codec used by the file. 2 null-terminated UTF-8 strings are returned, with the 1st string being the name of the codec, and the 2nd containing additional information like what VBR setting was used. + + + + + Media Foundation tags : A pointer to a series of null-terminated UTF-8 strings is returned, the final string ending with a double null. + + + + + WAVE format : A pointer to a structure is returned. + + + + + RIFF/WAVE tags : array of null-terminated ANSI strings. + + + + + BWF/RF64 tags (Broadcast Audio Extension) : A pointer to a variable length block is returned (see ). + See the EBU specification for details of the block's structure. + When reading BWF tags into a structure e.g. via the following mapping is performed if no RIFF_INFO tags are present: + Description = Title (max. 256 chars) + Originator = Artist (max. 32 chars) + OriginatorReference = EncodedBy (max. 32 chars) + OriginationDate = Year (in format 'yyyy-mm-dd hh:mm:ss') + TimeReference = Track + UMID = Copyright (max. 64 chars) + CodingHistory = Comment + However, if RIFF_INFO tags are present the BWF tags are present in the NativeTags. + + + + + RIFF/BWF Radio Traffic Extension tags : A pointer to a variable length block is returned (see ). + See the EBU specifications for details of the block's structure. + When reading BWF tags into a structure e.g. via the following mapping is performed if no RIFF_INFO tags are present: + Title = Title (max. 64 chars) + Artist = Artist (max. 64 chars) + Category = Grouping (max. 64 chars) + Classification = Mood (max. 64 chars) + ProducerAppID = Publisher (max. 64 chars) + ProducerAppVersion = EncodedBy (max. 64 chars) + TagText = Comment + However, if RIFF_INFO tags are present the CART tags are present in the NativeTags. + + + + + RIFF DISP text chunk: a single ANSI string. + + + + + + index# : structure. + + + + + MOD music name : a single ANSI string. + + + + + MOD message : a single ANSI string. + + + + + MOD music order list: BYTE array of pattern numbers played at that order position. + Pattern number 254 is "+++" (skip order) and 255 is "---" (end song). You can use with BASS_POS_MUSIC_ORDER to get the length of the array. + + + + + + + instrument#, MOD instrument name : ANSI string + + + + + + sample#, MOD sample name : ANSI string + + + + + + track#, track text : array of null-terminated ANSI strings + + + + + ADX tags: A pointer to the ADX loop structure (see ). + + + + + + index# : structure. + + + + + Unknown tags : not supported tags + + + + + Channel attribute options used by and . + + + + + The sample rate of a channel. + freq: The sample rate... 100 (min) to 100000 (max), 0 = original rate (when the channel was created). The value will be rounded down to a whole number. + This attribute applies to playback of the channel, and does not affect the channel's sample data, so has no real effect on decoding channels. It is still adjustable though, so that it can be used by the BassMix add-on, and anything else that wants to use it. + Although the standard valid sample rate range is 100 to 100000, some devices/drivers may have a different valid range. See the minrate and maxrate members of the structure. + It is not possible to change the sample rate of a channel if the "with FX flag" DX8 effect implementation enabled on it, unless DirectX 9 or above is installed. + It requires an increased amount of CPU processing to play MOD musics and streams at increased sample rates. If you plan to play MOD musics or streams at greatly increased sample rates, then you should increase the buffer lengths () to avoid possible break-ups in the sound. + + + + + The volume level of a channel. + volume: The volume level... 0 (silent) to 1 (full). + This attribute applies to playback of the channel, and does not affect the channel's sample data, so has no real effect on decoding channels. It is still adjustable though, so that it can be used by the BassMix add-on, and anything else that wants to use it. + When using to slide this attribute, a negative volume value can be used to fade-out and then stop the channel. + + + + + The panning/balance position of a channel. + pan: The pan position... -1 (full left) to +1 (full right), 0 = centre. + This attribute applies to playback of the channel, and does not affect the channel's sample data, so has no real effect on decoding channels. It is still adjustable though, so that it can be used by the BassMix add-on, and anything else that wants to use it. + It is not possible to set the pan position of a 3D channel. It is also not possible to set the pan position when using speaker assignment, but if needed, it can be done via a DSP function instead (not on mono channels). + Platform-specific + On Windows, this attribute has no effect when speaker assignment is used, except on Windows Vista and newer with the config option enabled. Balance control could be implemented via a DSP function instead + + + + + The wet (reverb) / dry (no reverb) mix ratio on a sample, stream, or MOD music channel with 3D functionality. + mix: The wet / dry ratio... 0 (full dry) to 1 (full wet), -1 = automatically calculate the mix based on the distance (the default). + Obviously, EAX functions have no effect if the output device does not support EAX. can be used to check that. EAX only affects 3D channels, but EAX functions do not require to apply the changes. + + + Additional ERROR CODEDescription + BASS_ERROR_NOEAXThe channel does not have EAX support. EAX only applies to 3D channels that are mixed by the hardware/drivers. can be used to check if a channel is being mixed by the hardware. + + + EAX is only supported on Windows. + + + + + Non-Windows: Disable playback buffering? + nobuffer: Disable playback buffering... 0 = no, else yes.. + A playing channel is normally asked to render data to its playback buffer in advance, via automatic buffer updates or the and functions, ready for mixing with other channels to produce the final mix that is given to the output device. + When this attribute is switched on (the default is off), that buffering is skipped and the channel will only be asked to produce data as it is needed during the generation of the final mix. This allows the lowest latency to be achieved, but also imposes tighter timing requirements on the channel to produce its data and apply any DSP/FX (and run mixtime syncs) that are set on it; if too long is taken, there will be a break in the output, affecting all channels that are playing on the same device. + The channel's data is still placed in its playback buffer when this attribute is on, which allows and to be used, although there is likely to be less data available to them due to the buffer being less full. + This attribute can be changed mid-playback. If switched on, any already buffered data will still be played, so that there is no break in sound. + This attribute is not available on Windows, as BASS does not generate the final mix. + + + + + The CPU usage of a channel. + cpu: The CPU usage (in percentage). + This attribute gives the percentage of CPU that the channel is using, including the time taken by decoding and DSP processing, and any FX that are not using the "with FX flag" DX8 effect implementation. It does not include the time taken to add the channel's data to the final output mix during playback. The processing of some add-on stream formats may also not be entirely included, if they use additional decoding threads; see the add-on documentation for details. + Like , this function does not strictly tell the CPU usage, but rather how timely the processing is. For example, if it takes 10ms to generate 100ms of data, that would be 10%. If the reported usage exceeds 100%, that means the channel's data is taking longer to generate than to play. The duration of the data is based on the channel's current sample rate (). + A channel's CPU usage is updated whenever it generates data. That could be during a playback buffer update cycle, or a call, or a call. For a decoding channel, it would be in a or call. + This attribute is read-only, so cannot be modified via . + + + + + The sample rate conversion quality of a channel. + quality: The sample rate conversion quality... 0 = linear interpolation, 1 = 8 point sinc interpolation, 2 = 16 point sinc interpolation, 3 = 32 point sinc interpolation. Other values are also accepted but will be interpreted as 0 or 3, depending on whether they are lower or higher. + When a channel has a different sample rate to what the output device is using, the channel's sample data will need to be converted to match the output device's rate during playback. This attribute determines how that is done. The linear interpolation option uses less CPU, but the sinc interpolation gives better sound quality (less aliasing), with the quality and CPU usage increasing with the number of points. A good compromise for lower spec systems could be to use sinc interpolation for music playback and linear interpolation for sound effects. + Whenever possible, a channel's sample rate should match the output device's rate to avoid the need for any sample rate conversion. The device's sample rate could be used in or or stream creation calls, for example. + The sample rate conversion occurs (when required) during playback, after the sample data has left the channel's playback buffer, so it does not affect the data delivered by . Although this attribute has no direct effect on decoding channels, it is still available so that it can be used by the add-on and anything else that wants to use it. + This attribute can be set at any time, and changes take immediate effect. A channel's initial setting is determined by the config option, or in the case of a sample channel. + Platform-specific + On Windows, sample rate conversion is handled by Windows or the output device/driver rather than BASS, so this setting has no effect on playback there. + + + + + The amplification level of a MOD music. + amp: Amplification level... 0 (min) to 100 (max). This will be rounded down to a whole number. + As the amplification level get's higher, the sample data's range increases, and therefore, the resolution increases. But if the level is set too high, then clipping can occur, which can result in distortion of the sound. + You can check the current level of a MOD music at any time by using . By doing so, you can decide if a MOD music's amplification level needs adjusting. + The default amplification level is 50. + During playback, the effect of changes to this attribute are not heard instantaneously, due to buffering. To reduce the delay, use the config option to reduce the buffer length. + + + + + The pan separation level of a MOD music. + pansep: Pan separation... 0 (min) to 100 (max), 50 = linear. This will be rounded down to a whole number. + By default BASS uses a linear panning "curve". If you want to use the panning of FT2, use a pan separation setting of around 35. To use the Amiga panning (ie. full left and right) set it to 100. + + + + + The position scaler of a MOD music. + scale: The scaler... 1 (min) to 256 (max). This will be rounded down to a whole number. + When calling , the row (HIWORD) will be scaled by this value. By using a higher scaler, you can get a more precise position indication. + The default scaler is 1. + + + Get the position of a MOD music accurate to within a 10th of a row: + + // set the scaler + Bass.BASS_ChannelSetAttribute(music, BASSAttribute.BASS_ATTRIB_MUSIC_PSCALER, 10f); + int pos = Bass.BASS_MusicGetOrderPosition(music); + // the order + int order = Utils.LowWord32(pos); + // the row + int row = HighWord32(pos) / 10; + // the 10th of a row + int row10th = HighWord32(pos) % 10; + + + ' set the scaler + Bass.BASS_ChannelSetAttribute(music, BASSAttribute.BASS_ATTRIB_MUSIC_PSCALER, 10F) + Dim pos As Integer = Bass.BASS_MusicGetOrderPosition(music) + ' the order + Dim order As Integer = Utils.LowWord32(pos) + ' the row + Dim row As Integer = HighWord32(pos) / 10 + ' the 10th of a row + Dim row10th As Integer = HighWord32(pos) Mod 10 + + + + + + + + The BPM of a MOD music. + bpm: The BPM... 1 (min) to 255 (max). This will be rounded down to a whole number. + This attribute is a direct mapping of the MOD's BPM, so the value can be changed via effects in the MOD itself. + Note that by changing this attribute, you are changing the playback length. + During playback, the effect of changes to this attribute are not heard instantaneously, due to buffering. To reduce the delay, use the config option to reduce the buffer length. + + + + + The speed of a MOD music. + speed: The speed... 0 (min) to 255 (max). This will be rounded down to a whole number. + This attribute is a direct mapping of the MOD's speed, so the value can be changed via effects in the MOD itself. + The "speed" is the number of ticks per row. Setting it to 0, stops and ends the music. Note that by changing this attribute, you are changing the playback length. + During playback, the effect of changes to this attribute are not heard instantaneously, due to buffering. To reduce the delay, use the config option to reduce the buffer length. + + + + + The global volume level of a MOD music. + volume: The global volume level... 0 (min) to 64 (max, 128 for IT format). This will be rounded down to a whole number. + This attribute is a direct mapping of the MOD's global volume, so the value can be changed via effects in the MOD itself. + The "speed" is the number of ticks per row. Setting it to 0, stops and ends the music. Note that by changing this attribute, you are changing the playback length. + During playback, the effect of changes to this attribute are not heard instantaneously, due to buffering. To reduce the delay, use the config option to reduce the buffer length. + + + + + The volume level of a channel in a MOD music + channel#. + channel: The channel to set the volume of... 0 = 1st channel. + volume: The volume level... 0 (silent) to 1 (full). + The volume curve used by this attribute is always linear, eg. 0.5 = 50%. The config option setting has no effect on this. The volume level of all channels is initially 1 (full). + This attribute can also be used to count the number of channels in a MOD Music. + During playback, the effect of changes to this attribute are not heard instantaneously, due to buffering. To reduce the delay, use the config option to reduce the buffer length. + + + Count the number of channels in a MOD music: + + int channels = 0; + float dummy; + while (Bass.BASS_ChannelGetAttribute(music, (BASSAttribute)((int)BASS_ATTRIB_MUSIC_VOL_CHAN + channels), ref dummy)) + { + channels++; + } + + + Dim channels As Integer = 0 + Dim dummy As Single + While Bass.BASS_ChannelGetAttribute(music, CType(CInt(BASS_ATTRIB_MUSIC_VOL_CHAN) + channels, BASSAttribute), dummy) + channels += 1 + End While + + + + + + + + The volume level of an instrument in a MOD music + inst#. + inst: The instrument to set the volume of... 0 = 1st instrument. + volume: The volume level... 0 (silent) to 1 (full). + The volume curve used by this attribute is always linear, eg. 0.5 = 50%. The config option setting has no effect on this. The volume level of all instruments is initially 1 (full). For MOD formats that do not use instruments, read "sample" for "instrument". + This attribute can also be used to count the number of instruments in a MOD music. + During playback, the effect of changes to this attribute are not heard instantaneously, due to buffering. To reduce the delay, use the config option to reduce the buffer length. + + + Count the number of instruments in a MOD music: + + int instruments = 0; + float dummy; + while (Bass.BASS_ChannelGetAttribute(music, (BASSAttribute)((int)BASSAttribute.BASS_ATTRIB_MUSIC_VOL_INST + instruments), ref dummy)) + { + instruments++; + } + + + Dim instruments As Integer = 0 + Dim dummy As Single + While Bass.BASS_ChannelGetAttribute(music, CType(CInt(BASSAttribute.BASS_ATTRIB_MUSIC_VOL_INST) + instruments, BASSAttribute), dummy) + instruments += 1 + End While + + + + + + + + BASS_FX Tempo: The Tempo in percents (-95%..0..+5000%). + + + + + BASS_FX Tempo: The Pitch in semitones (-60..0..+60). + + + + + BASS_FX Tempo: The Samplerate in Hz, but calculates by the same % as BASS_ATTRIB_TEMPO. + + + + + BASS_FX Tempo Option: Use FIR low-pass (anti-alias) filter (gain speed, lose quality)? =1 (default), =0. + See for details. + + + + + BASS_FX Tempo Option: FIR low-pass (anti-alias) filter length in taps (8 .. 128 taps, default = 32, should be %4). + See for details. + + + + + BASS_FX Tempo Option: Use quicker tempo change algorithm (gain speed, lose quality)? =1, =0 (default). + See for details. + + + + + BASS_FX Tempo Option: Tempo Sequence in milliseconds (default = 82). + See for details. + + + + + BASS_FX Tempo Option: SeekWindow in milliseconds (default = 14). + See for details. + + + + + BASS_FX Tempo Option: Tempo Overlap in milliseconds (default = 12). + See for details. + + + + + BASS_FX Tempo Option: Prevents clicks with tempo changes (default = FALSE). + See for details. + + + + + BASS_FX Reverse: The Playback direction (-1=BASS_FX_RVS_REVERSE or 1=BASS_FX_RVS_FORWARD). + + + + + BASSMIDI: Gets the Pulses Per Quarter Note (or ticks per beat) value of the MIDI file. + ppqn: The PPQN value. + This attribute is the number of ticks per beat as defined by the MIDI file; it will be 0 for MIDI streams created via , + It is also read-only, so can't be modified via . + + + Get the currnet position of a MIDI stream in beats: + + float ppqn; + Bass.BASS_ChannelGetAttribute(midi, BASSAttribute.BASS_ATTRIB_MIDI_PPQN, ref ppqn); + long tick = Bass.BASS_ChannelGetPosition(midi, BASSMode.BASS_POS_MIDI_TICK); + float beat = tick / ppqn; + + + Dim ppqn As Single + Bass.BASS_ChannelGetAttribute(midi, BASSAttribute.BASS_ATTRIB_MIDI_PPQN, ppqn) + Dim tick As Long = Bass.BASS_ChannelGetPosition(midi, BASSMode.BASS_POS_MIDI_TICK) + Dim beat As Single = tick / ppqn + + + + + + + + BASSMIDI: The maximum percentage of CPU time that a MIDI stream can use. + limit: The CPU usage limit... 0 to 100, 0 = unlimited. + It is not strictly the CPU usage that is measured, but rather how timely the stream is able to render data. + For example, a limit of 50% would mean that the rendering would need to be at least 2x real-time speed. When the limit is exceeded, BASSMIDI will begin killing voices, starting with the most quiet. + By default, a MIDI stream will have no CPU limit. + + + + + BASSMIDI: The number of MIDI channels in a MIDI stream. + channels: The number of MIDI channels... 1 (min) - 128 (max). For a MIDI file stream, the minimum is 16. + New channels are melodic by default. Any notes playing on a removed channel are immediately stopped. + + + + + BASSMIDI: The maximum number of samples to play at a time (polyphony) in a MIDI stream. + voices: The number of voices... 1 (min) - 256 (max). + If there are currently more voices active than the new limit, then some voices will be killed to meet the limit. + A MIDI stream will initially have a default number of voices as determined by the config option. + + + + + BASSMIDI: The volume level of a track in a MIDI file stream + track#. + track#: The track to set the volume of... 0 = first track. + volume: The volume level (0.0=silent, 1.0=normal/default). + The volume curve used by this attribute is always linear, eg. 0.5 = 50%. The BASS_CONFIG_CURVE_VOL config option setting has no effect on this. + During playback, the effect of changes to this attribute are not heard instantaneously, due to buffering. To reduce the delay, use the BASS_CONFIG_BUFFER config option to reduce the buffer length. + This attribute can also be used to count the number of tracks in a MIDI file stream. MIDI streams created via do not have any tracks. + + + Count the number of tracks in a MIDI stream: + + int tracks = 0; + float dummy; + while (Bass.BASS_ChannelGetAttribute(midi, (BASSAttribute)((int)BASSAttribute.BASS_ATTRIB_MIDI_TRACK_VOL + tracks), ref dummy)) + { + tracks++; + } + + + Dim tracks As Integer = 0 + Dim dummy As Single + While Bass.BASS_ChannelGetAttribute(midi, CType(CInt(BASSAttribute.BASS_ATTRIB_MIDI_TRACK_VOL) + tracks, BASSAttribute), dummy) + tracks += 1 + End While + + + + + + + + Sync types to be used with (param flag) and (data flag). + + + + + Sync when a channel reaches a position. + param : position in bytes + data : not used + + + + + Sync when an instrument (sample for the non-instrument based formats) is played in a MOD music (not including retrigs). + param : LOWORD=instrument (1=first) HIWORD=note (0=c0...119=b9, -1=all) + data : LOWORD=note HIWORD=volume (0-64) + + + + + Sync when a channel reaches the end. + param : not used + data : 1 = the sync is triggered by a backward jump in a MOD music, otherwise not used + + + + + Sync when the "sync" effect (XM/MTM/MOD: E8x/Wxx, IT/S3M: S2x) is used. + param : 0:data=pos, 1:data="x" value + data : param=0: LOWORD=order HIWORD=row, param=1: "x" value + + + + + Sync when metadata is received in a stream. + param : not used + data : not used - the updated metadata is available from (BASS_TAG_META) + + + + + Sync when an attribute slide is completed. + param : not used + data : the type of slide completed (one of the BASS_SLIDE_xxx values) + + + + + Sync when playback has stalled. + param : not used + data : 0=stalled, 1=resumed + + + + + Sync when downloading of an internet (or "buffered" user file) stream has ended. + param : not used + data : not used + + + + + Sync when a channel is freed. + param : not used + data : not used + + + + + Sync when a MOD music reaches an order:row position. + param : LOWORD=order (0=first, -1=all) HIWORD=row (0=first, -1=all) + data : LOWORD=order HIWORD=row + + + + + Sync when seeking (inc. looping and restarting). So it could be used to reset DSP/etc. + param : position in bytes + data : 0=playback is unbroken, 1=if is it broken (eg. buffer flushed). The latter would be the time to reset DSP/etc. + + + + + Sync when a new logical bitstream begins in a chained OGG stream. Updated tags are available from . + param : not used + data : not used + + + + + FLAG: sync at mixtime, else at playtime + + + + + FLAG: sync only once, else continuously + + + + + MIX add-on: Sync when an envelope reaches the end. + param : not used + data : envelope type + + + + + MIX add-on: Sync when an envelope node is reached. + param : Optional limit the sync to a certain envelope type (one of the values). + data : Will contain the envelope type in the LOWORD and the current node number in the HIWORD. + + + + + WMA add-on: Sync on a track change in a server-side playlist. Updated tags are available via . + param : not used + data : not used + + + + + WMA add-on: Sync on a mid-stream tag change in a server-side playlist. Updated tags are available via . + param : not used + data : not used - the updated metadata is available from (BASS_TAG_WMA_META) + + + + + CD add-on: Sync when playback is stopped due to an error. For example, the drive door being opened. + param : not used + data : the position that was being read from the CD track at the time. + + + + + CD add-on: Sync when the read speed is automatically changed due to the BASS_CONFIG_CD_AUTOSPEED setting. + param : not used + data : the new read speed. + + + + + WINAMP add-on: Sync when bitrate is changed or retrieved from a winamp input plug-in. + param : not used + data : the bitrate retrieved from the winamp input plug-in - called when it is retrieved or changed (VBR MP3s, OGGs, etc). + + + + + MIDI add-on: Sync when a marker is encountered. + param : not used + data : the marker index, which can be used in a call. + + + + private void MidiSync(int handle, int channel, int data, IntPtr user) + { + BASS_MIDI_MARK mark = BassMidi.BASS_MIDI_StreamGetMark(channel, BASSMIDIMarker.BASS_MIDI_MARK_MARKER, data); + ... + } + + + Private Sub MidiSync(handle As Integer, channel As Integer, data As Integer, user As IntPtr) + Dim mark As BASS_MIDI_MARK = BassMidi.BASS_MIDI_StreamGetMark(channel, BASSMIDIMarker.BASS_MIDI_MARK_MARKER, data) + ... + End Sub + + + + + + + + MIDI add-on: Sync when a cue is encountered. + param : not used + data : the marker index, which can be used in a call. + + + + private void MidiSync(int handle, int channel, int data, IntPtr user) + { + BASS_MIDI_MARK mark = BassMidi.BASS_MIDI_StreamGetMark(channel, BASSMIDIMarker.BASS_MIDI_MARK_CUE, data); + ... + } + + + Private Sub MidiSync(handle As Integer, channel As Integer, data As Integer, user As IntPtr) + Dim mark As BASS_MIDI_MARK = BassMidi.BASS_MIDI_StreamGetMark(channel, BASSMIDIMarker.BASS_MIDI_MARK_CUE, data) + ... + End Sub + + + + + + + + MIDI add-on: Sync when a lyric event is encountered. + param : not used + data : the marker index, which can be used in a call. + If the text begins with a '/' (slash) character, a new line should be started. If it begins with a '\' (backslash) character, the display should be cleared. + + + + private void MidiSync(int handle, int channel, int data, IntPtr user) + { + BASS_MIDI_MARK mark = BassMidi.BASS_MIDI_StreamGetMark(channel, BASSMIDIMarker.BASS_MIDI_MARK_LYRIC, data); + ... + } + + + Private Sub MidiSync(handle As Integer, channel As Integer, data As Integer, user As IntPtr) + Dim mark As BASS_MIDI_MARK = BassMidi.BASS_MIDI_StreamGetMark(channel, BASSMIDIMarker.BASS_MIDI_MARK_LYRIC, data) + ... + End Sub + + + + + + + + MIDI add-on: Sync when a text event is encountered. + param : not used + data : the marker index, which can be used in a call. + Lyrics can sometimes be found in BASS_MIDI_MARK_TEXT instead of BASS_MIDI_MARK_LYRIC markers. + + + + private void MidiSync(int handle, int channel, int data, IntPtr user) + { + BASS_MIDI_MARK mark = BassMidi.BASS_MIDI_StreamGetMark(channel, BASSMIDIMarker.BASS_SYNC_MIDI_TEXT, data); + ... + } + + + Private Sub MidiSync(handle As Integer, channel As Integer, data As Integer, user As IntPtr) + Dim mark As BASS_MIDI_MARK = BassMidi.BASS_MIDI_StreamGetMark(channel, BASSMIDIMarker.BASS_SYNC_MIDI_TEXT, data) + ... + End Sub + + + + + + + + MIDI add-on: Sync when a type of event is processed, in either a MIDI file or . + param : event type. + data : LOWORD = event parameter, HIWORD = channel. See for a list of event types and their parameters. + + + + + MIDI add-on: Sync when reaching a tick position. + param : tick position. + data : not used + + + + + MIDI add-on: Sync when a time signature event is processed. + param : event type. + data : The time signature events are given (by ) in the form of "numerator/denominator metronome-pulse 32nd-notes-per-MIDI-quarter-note", eg. "4/4 24 8". + + + + + MIDI add-on: Sync when a key signature event is processed. + param : event type. + data : The key signature events are given (by ) in the form of "a b", where a is the number of sharps (if positive) or flats (if negative), and b signifies major (if 0) or minor (if 1). + + + + + FX effect types, use with . + + + + + DX8 Chorus. Use structure to set/get parameters. + + + + + DX8 Compressor. Use structure to set/get parameters. + + + + + DX8 Distortion. Use structure to set/get parameters. + + + + + DX8 Echo. Use structure to set/get parameters. + + + + + DX8 Flanger. Use structure to set/get parameters. + + + + + DX8 Gargle. Use structure to set/get parameters. + + + + + DX8 I3DL2 (Interactive 3D Audio Level 2) reverb. Use structure to set/get parameters. + + + + + DX8 Parametric equalizer. Use structure to set/get parameters. + + + + + DX8 Reverb. Use structure to set/get parameters. + + + + + BASS_FX Channel Volume Ping-Pong (stereo channel only). No parameters to get or set. + + + + + BASS_FX Echo (2 channels max). Use structure to set/get parameters. + + + + + BASS_FX Flanger (multi channel). Use structure to set/get parameters. + + + + + BASS_FX Volume control (multi channel). Use structure to set/get parameters. + + + + + BASS_FX Peaking Equalizer (multi channel). Use structure to set/get parameters. + + + + + BASS_FX Reverb (2 channels max). Use structure to set/get parameters. + + + + + BASS_FX Low Pass Filter (multi channel). Use structure to set/get parameters. + + + + + BASS_FX Channel Swap/Remap/Downmix (multi channel). Use structure to set/get parameters. + + + + + BASS_FX Dynamic Amplification (multi channel). Use structure to set/get parameters. + + + + + BASS_FX Auto WAH (multi channel). Use structure to set/get parameters. + + + + + BASS_FX Echo 2 (multi channel). Use structure to set/get parameters. + + + + + BASS_FX Phaser (multi channel). Use structure to set/get parameters. + + + + + BASS_FX Echo 3 (multi channel). Use structure to set/get parameters. + + + + + BASS_FX Chorus (multi channel). Use structure to set/get parameters. + + + + + BASS_FX All Pass Filter (multi channel). Use structure to set/get parameters. + + + + + BASS_FX Dynamic Range Compressor (multi channel). Use structure to set/get parameters. + + + + + BASS_FX Distortion (multi channel). Use structure to set/get parameters. + + + + + BASS_FX Dynamic Range Compressor (multi channel). Use structure to set/get parameters. + + + + + BASS_FX Volume Envelope (multi channel). Use structure to set/get parameters. + + + + + BASS_FX BiQuad filters (multi channel). Use structure to set/get parameters. + + + + + DX8 effect types, use with e.g. the and effect. + + + + + Phase differential between left and right LFOs (-180) + + + + + Phase differential between left and right LFOs (-90) + + + + + Phase differential between left and right LFOs (+/-0) + + + + + Phase differential between left and right LFOs (+90) + + + + + Phase differential between left and right LFOs (+180) + + + + + Defines possible wave formats to be used with the flag. + + See the MMREG.H file for more codec numbers. + + + + Unknown Format + + + + + PCM format (8 or 16 bit), Microsoft Corporation + + + + + AD PCM Format, Microsoft Corporation + + + + + IEEE PCM Float format (32 bit) + + + + + AC2, Dolby Laboratories + + + + + GSM 6.10, Microsoft Corporation + + + + + MSN Audio, Microsoft Corporation + + + + + MPEG format + + + + + ISO/MPEG Layer3 Format + + + + + AC3 Digital, Sonic Foundry + + + + + Raw AAC + + + + + Microsoft Corporation + + + + + Windows Media Audio. This format is valid for versions 2 through 9 + + + + + Windows Media Audio 9 Professional + + + + + Windows Media Audio 9 Lossless + + + + + Windows Media SPDIF Digital Audio + + + + + ADTS AAC Audio + + + + + Raw AAC + + + + + MPEG-4 audio transport stream with a synchronization layer (LOAS) and a multiplex layer (LATM) + + + + + High-Efficiency Advanced Audio Coding (HE-AAC) stream + + + + + Extensible Format (user defined) + + + + + Used with to retrieve information on the supported plugin formats. + + The plugin information does not change, so the returned pointer remains valid for as long as the plugin is loaded. + The extension filter is for information only. A plugin will check the file contents rather than file extension, to verify that it is a supported format. + + + + + The channel type, as would appear in the structure. + + + + + The Format description or name. + + + + + File extension filter, in the form of "*.ext1;*.ext2;etc...". + + The extension filter is for information only. A plugin will check the file contents rather than file extension, to verify that it is a supported format. + + + + Default constructor. + + + + + Constructor. + + The channel type, as would appear in the structure. + The Format description or name. + File extension filter, in the form of "*.ext1;*.ext2;etc...". + + + + A description of the plugin format (name|exts) which can be used for file filter settings. + + The file filter of the plugin format (name|exts). + + + + Only used internally! See . + + + + + plugin version (same form as BASS_GetVersion). + + + + + Number of supported formats. + + + + + The pointer to the array of supported formats. The array contains formatc elements. + + + + + Used with to retrieve information on a plugin. + + This class can not be used directly! It will be returned and created by only. + + + + Plugin version, in the same form as given by . + + + + + Number of supported formats. + + + + + The array of supported formats. The array contains number of elements. + + + Note: There is no guarantee that the list of supported formats is complete or might contain formats not being supported on your particular OS/machine (due to additional or missing audio codecs). + + + + + An instance of this class can not be created directly. Use instead. + + + + + Internal Constructor. + + The formats to use. + The version of the plugin. + + + + Constructor. Can be used with the return value of . + + A pointer to the structure. + Should only be used with the return value of . + + + + Constructor + + The version of the plugin. + The number of supported formats. + The pointer to the array of supported formats + Only used internally. + + + + Reads in the array. + + Number of array elements to read. + The pointer to the first array element. + + + + A description of the plugin structure (version, formatc). + + A description of the plugin structure (version, formatc). + + + + Used with or to retrieve information on a device. + + + When a device is disabled/disconnected, it is still retained in the device list, but the BASS_DEVICE_ENABLED flag is removed from it. If the device is subsequently re-enabled, it may become available again with the same device number, or the system may add a new entry for it. + When a new device is connected, it can affect the other devices and result in the system moving them to new device entries. If an affected device is initialized, it will stop working and will need to be reinitialized using its new device number. + Platform-specific + On Windows, driver can reveal the type of driver being used on systems that support both VxD and WDM drivers (Windows Me/98SE). + Further information can be obtained from the file via the GetFileVersionInfo function. On Vista and above, the device's endpoint ID is given rather than its driver filename. On Linux, driver is the ALSA device name. It is unused on other platforms. + Depending on the config setting, name and driver can be in ANSI or UTF-8 form on Windows. + They are always in UTF-16 form on Windows CE, and UTF-8 on other platforms - note, that Bass.Net always enables the Unicode form and does all the conversion for you by default! + + + + + + The description of the device. + + + + + The filename of the driver being used... = no driver (ie. "no sound" device). + On systems that can use both VxD and WDM drivers (Windows Me/98SE), this will reveal which type of driver is being used. + Further information can be obtained from the file using the GetFileVersionInfo Win32 API function. + + + + + The driver id resp. interface name being used... = no id (ie. interface name is not available). + Only available on Vista/Win7 systems. + + + + + The device's current status. A combination of these flags (): + + BASS_DEVICE_ENABLEDThe device is enabled. It will not be possible to initialize the device if this flag is not present. + BASS_DEVICE_DEFAULTThe device is the system default. + BASS_DEVICE_INITThe device is initialized, ie. or has been called. + + + + + + Default constructor. + + + + + A description of the decive info object (name). + + A description of the decive info object (name). + + + + The device is enabled and can be used. + + + + + The device is the system default device. + + + + + The device is already initialized. + + + + + Used with to retrieve information on the current device. + + + The DSCAPS_SECONDARY flags only indicate which sample formats are supported by hardware mixing. + Platform-specific + On Windows, it is possible for speakers to mistakenly be 2 with some devices/drivers when the device in fact supports more speakers. In that case, the BASS_DEVICE_CPSPEAKERS flag can be used (with ) to use the Windows control panel setting, or the BASS_DEVICE_SPEAKERS flag can be used to force the enabling of speaker assignment to up to 8 speakers, even though the device may not really support that many speakers. The result of assigning channels to nonexistent speakers is undefined; they may be heard on other speakers, or not heard at all. + The flags, hwsize, hwfree, freesam, free3d, minrate, maxrate, eax, and dsver members are only used on Windows, as DirectSound and hardware mixing are only available there. The freq member is not available on Windows prior to Vista. + On Windows, the availability of the latency and minbuf values depends on the BASS_DEVICE_LATENCY flag being used when was called. + + + + + The device's capabilities. A combination of these flags (): + + DSCAPS_CONTINUOUSRATEThe device supports all sample rates between minrate and maxrate. + DSCAPS_EMULDRIVERThe device's drivers do NOT have DirectSound support, so it is being emulated. Updated drivers should be installed. + DSCAPS_CERTIFIEDThe device driver has been certified by Microsoft. This flag is always set on WDM drivers. + DSCAPS_SECONDARYMONOMono samples are supported by hardware mixing. + DSCAPS_SECONDARYSTEREOStereo samples are supported by hardware mixing. + DSCAPS_SECONDARY8BIT8-bit samples are supported by hardware mixing. + DSCAPS_SECONDARY16BIT16-bit samples are supported by hardware mixing. + + + + + + The device's total amount of hardware memory. + + + + + The device's amount of free hardware memory. + + + + + The number of free sample slots in the hardware. + + + + + The number of free 3D sample slots in the hardware. + + + + + The minimum sample rate supported by the hardware. + + + + + The maximum sample rate supported by the hardware. + + + + The device supports EAX and has it enabled? + The device's "Hardware acceleration" needs to be set to "Full" in it's "Advanced Properties" setup, else EAX is disabled. + This is always if BASS_DEVICE_3D was not used when was called. + + + + The minimum buffer length (rounded up to the nearest millisecond) recommended for use with the BASS_CONFIG_BUFFER config option (see and ). + Requires that BASS_DEVICE_LATENCY was used when was called. + + + + + DirectSound version. + 9 = DX9/8/7/5 features are available, 8 = DX8/7/5 features are available, 7 = DX7/5 features are available, 5 = DX5 features are available. 0 = none of the DX9/8/7/5 features are available. + + + + The delay (rounded up to the nearest millisecond) for playback of HSTREAM/HMUSIC channels to start and be heard. + Requires that BASS_DEVICE_LATENCY was used when was called. + + + + + The flags parameter of the call (). + + + + The number of speakers the device/drivers supports... 2 means that there is no support for speaker assignment - this will always be the case with non-WDM drivers in Windows. + It's also possible that it could mistakenly be 2 with some devices/drivers, when the device in fact supports more speakers. + In that case the BASS_DEVICE_SPEAKERS or BASS_DEVICE_CPSPEAKERS flag can be used in the call to force the enabling of speaker assignment. + + + + + The device's current output sample rate. This is only available on Windows Vista and OSX. + + + + + Default constructor. + + + + + A description of the decive info object (speakers, rates, dx, eax). + + A description of the decive info object (speakers, rates, dx, eax). + + + + The device supports all sample rates between minrate and maxrate. + + + + + The device's drivers has DirectSound support + + + + + The device driver has been certified by Microsoft. Always true for WDM drivers. + + + + + Mono samples are supported by hardware mixing. + + + + + Stereo samples are supported by hardware mixing. + + + + + 8-bit samples are supported by hardware mixing. + + + + + 16-bit samples are supported by hardware mixing. + + + + + Used with to retrieve information on the current recording device. + + + The formats member does not represent all the formats supported by the device, just the "standard" ones. + If there is no DirectSound driver for the device (ie. it's being emulated), then the driver member will contain something like "WaveIn" instead of a filename. + Platform-specific + The flags and formats members are only used on Windows, and formats does not necessarily represent all of the formats supported by the device, just the "standard" ones. freq is not available on Windows prior to Vista. + + + + + The device's capabilities . + A combination of these flags (see ): + + DSCCAPS_EMULDRIVERThe device's drivers do NOT have DirectSound recording support, so it is being emulated. + DSCCAPS_CERTIFIEDThe device driver has been certified by Microsoft. + + + + + + The standard formats supported by the device (default is WAVE_FORMAT_4S16). + A combination of these flags (see ): + + WAVE_FORMAT_1M0811025hz, Mono, 8-bit + WAVE_FORMAT_1S0811025hz, Stereo, 8-bit + WAVE_FORMAT_1M1611025hz, Mono, 16-bit + WAVE_FORMAT_1S1611025hz, Stereo, 16-bit + WAVE_FORMAT_2M0822050hz, Mono, 8-bit + WAVE_FORMAT_2S0822050hz, Stereo, 8-bit + WAVE_FORMAT_2M1622050hz, Mono, 16-bit + WAVE_FORMAT_2S1622050hz, Stereo, 16-bit + WAVE_FORMAT_4M0844100hz, Mono, 8-bit + WAVE_FORMAT_4S0844100hz, Stereo, 8-bit + WAVE_FORMAT_4M1644100hz, Mono, 16-bit + WAVE_FORMAT_4S1644100hz, Stereo, 16-bit + + + + + + The number of input sources available to the device + + + + + = only one input may be active at a time + + + + + The device's current input sample rate. This is only available on Windows Vista and OSX. + + + + + Default constructor. + + + + + A description of the record decive info object (inputs, singlein). + + A description of the record decive info object (inputs, singlein). + + + + The device's drivers has DirectSound support + + + + + The device driver has been certified by Microsoft. Always true for WDM drivers. + + + + + Table of callback functions used with . + + A copy is made of the procs callback function table, so it does not have to persist beyond this function call. + This means it is not required to pin the 'procs' instance, but it is still required to keep a reference as long as BASS uses the callback delegates in order to prevent the callbacks from being garbage collected. + + + + using Un4seen.Bass; + ... + private BASS_FILEPROCS _myStreamCreateUser; + private FileStream _fs; + ... + Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, this.Handle); + // creating the user file callback delegates + _myStreamCreateUser = new BASS_FILEPROCS( + new FILECLOSEPROC(MyFileProcUserClose), + new FILELENPROC(MyFileProcUserLength), + new FILEREADPROC(MyFileProcUserRead), + new FILESEEKPROC(MyFileProcUserSeek)); + // open the file... + _fs = File.OpenRead("test.mp3"); + // create the stream (the PRESCAN flag shows you what BASS is doing at the beginning to scan the entire file) + // if that generates to much output for you, you can simply remove it + int stream = Bass.BASS_StreamCreateFileUser(BASSStreamSystem.STREAMFILE_NOBUFFER, BASSFlag.BASS_STREAM_PRESCAN | BASSFlag.BASS_STREAM_AUTOFREE, _myStreamCreateUser, IntPtr.Zero); + // play the channel + Bass.BASS_ChannelPlay(stream, false); + ... + private void MyFileProcUserClose(IntPtr user) + { + if (_fs == null) + return; + _fs.Close(); + Console.WriteLine("File Closed"); + } + + private long MyFileProcUserLength(IntPtr user) + { + if (_fs == null) + return 0L; + return _fs.Length; + } + + private int MyFileProcUserRead(IntPtr buffer, int length, IntPtr user) + { + if (_fs == null) + return 0; + try + { + // at first we need to create a byte[] with the size of the requested length + byte[] data = new byte[length]; + // read the file into data + int bytesread = _fs.Read(data, 0, length); + // and now we need to copy the data to the buffer + // we write as many bytes as we read via the file operation + Marshal.Copy(data, 0, buffer, bytesread); + return bytesread; + } + catch { return 0; } + } + + private bool MyFileProcUserSeek(long offset, IntPtr user) + { + if (_fs == null) + return false; + try + { + long pos = _fs.Seek(offset, SeekOrigin.Begin); + return true; + } + catch + { + return false; + } + } + + + Imports Un4seen.Bass + ... + Private _myStreamCreateUser As BASS_FILEPROCS + Private _fs As FileStream + ... + Bass.BASS_Init(- 1, 44100, BASSInit.BASS_DEVICE_DEFAULT, Me.Handle) + ' creating the user file callback delegates + _myStreamCreateUser = New BASS_FILEPROCS( + New FILECLOSEPROC(AddressOf MyFileProcUserClose), + New FILELENPROC(AddressOf MyFileProcUserLength), + New FILEREADPROC(AddressOf MyFileProcUserRead), + New FILESEEKPROC(AddressOf MyFileProcUserSeek)) + ' open the file... + _fs = File.OpenRead("test.mp3") + ' create the stream (the PRESCAN flag shows you what BASS is doing at the beginning to scan the entire file) + ' if that generates to much output for you, you can simply remove it + Dim stream As Integer = Bass.BASS_StreamCreateFileUser(BASSStreamSystem.STREAMFILE_NOBUFFER, BASSFlag.BASS_STREAM_PRESCAN Or BASSFlag.BASS_STREAM_AUTOFREE, _myStreamCreateUser, IntPtr.Zero) + ' play the channel + Bass.BASS_ChannelPlay(stream, False) + ... + Private Sub MyFileProcUserClose(user As IntPtr) + If _fs Is Nothing Then + Return + End If + _fs.Close() + End Sub + + Private Function MyFileProcUserLength(user As IntPtr) As Long + If _fs Is Nothing Then + Return 0L + End If + Return _fs.Length + End Function + + Private Function MyFileProcUserRead(buffer As IntPtr, length As Integer, user As IntPtr) As Integer + If _fs Is Nothing Then + Return 0 + End If + Try + ' at first we need to create a byte[] with the size of the requested length + Dim data(length - 1) As Byte + ' read the file into data + Dim bytesread As Integer = _fs.Read(data, 0, length) + ' and now we need to copy the data to the buffer + ' we write as many bytes as we read via the file operation + Marshal.Copy(data, 0, buffer, bytesread) + Return bytesread + Catch + Return 0 + End Try + End Function + + Private Function MyFileProcUserSeek(offset As Long, user As IntPtr) As Boolean + If _fs Is Nothing Then + Return False + End If + Try + Dim pos As Long = _fs.Seek(offset, SeekOrigin.Begin) + Return True + Catch + Return False + End Try + End Function + + + + + + Callback function to close the file. + + + + + Callback function to get the file length. + + + + + Callback function to read from the file. + + + + + Callback function to seek in the file. Not used by buffered file streams. + + + + + Default constructor taking the callback delegates. + + The callback to use. + The callback to use. + The callback to use. + The callback to use. + + + + Used with and to retrieve and set the default playback attributes of a sample. + + + When a sample has 3D functionality, the iangle and oangle angles decide how wide the sound is projected around the orientation angle (as set via ). + Within the inside angle the volume level is the level set in the volume member (or as set with when the sample is playing). + Outside the outer angle, the volume changes according to the outvol value. Between the inner and outer angles, the volume gradually changes between the inner and outer volume levels. + If the inner and outer angles are 360 degrees, then the sound is transmitted equally in all directions. + BASS supports 8 & 16-bit samples, so if a WAV file, for example, uses another sample resolution, it'll have to be converted by BASS. + The origres member can be used to check what the resolution originally was. + When VAM is enabled, and neither the BASS_VAM_HARDWARE or BASS_VAM_SOFTWARE flags are specified, then the sample will be played in hardware if resources are available, and in software if no hardware resources are available. + + + + + Default playback rate (set to 44100 by default). + + + + + Default volume... 0 (silent) to 1 (full, default). + + + + + Default panning position -1 (full left) to +1 (full right) - defaulted to 0 = centre. + + + + + A combination of these flags (): + + BASS_SAMPLE_8BITSThe samples's resolution is 8-bit. If neither this or the BASS_SAMPLE_FLOAT flags are present, then the sample's resolution is 16-bit. + BASS_SAMPLE_FLOATThe samples's resolution is 32-bit floating-point. + BASS_SAMPLE_LOOPLooped? + BASS_SAMPLE_3DThe sample has 3D functionality enabled. + BASS_SAMPLE_MUTEMAX Mute the sample when it is at (or beyond) it's max distance (3D samples only). + BASS_SAMPLE_SOFTWAREThe sample is not using hardware mixing... it is being mixed in software by DirectSound. + BASS_SAMPLE_VAMDX7 voice allocation and management features are enabled (see below). + BASS_SAMPLE_OVER_VOLOverride: the channel with the lowest volume is overriden. + BASS_SAMPLE_OVER_POSOverride: the longest playing channel is overriden. + BASS_SAMPLE_OVER_DISTOverride: the channel furthest away (from the listener) is overriden (3D samples only). + + + + + + The length in bytes. + + + + + Maximum number of simultaneous playbacks (defaulted to 1). + + + + + The original resolution (bits per sample)... 0 = undefined (default). + + + + + Number of channels... 1=mono, 2=stereo (default), etc. + + + + + Minimum time gap in milliseconds between creating channels using . + This can be used to prevent flanging effects caused by playing a sample multiple times very close to eachother. + The default setting, when loading/creating a sample, is 0 (disabled). + + + + + The 3D processing mode... one of these flags (see ): + + BASS_3DMODE_NORMALNormal 3D processing (default). + BASS_3DMODE_RELATIVEThe sample's 3D position (position/velocity/orientation) is relative to the listener. When the listener's position/velocity/orientation is changed with , the sample's position relative to the listener does not change. + BASS_3DMODE_OFFTurn off 3D processing on the sample, the sound will be played in the center. + + + + + + The minimum distance (default 0). The sample's volume is at maximum when the listener is within this distance. + + + + + The maximum distance (default 0). The sample's volume stops decreasing when the listener is beyond this distance. + + + + + The angle of the inside projection cone in degrees... 0 (no cone, default) - 360 (sphere). + + + + + The angle of the outside projection cone in degrees... 0 (no cone, default) - 360 (sphere). + + + + + The delta-volume outside the outer projection cone... 0 (silent) to 1 (full, default) - same as inside the cone. + + + + + The following are the sample's DX7 voice allocation/management settings (if VAM is enabled)...a combination of these (): + + BASS_VAM_HARDWAREPlay the sample in hardware (default). If no hardware voices are available then the play call will fail. + BASS_VAM_SOFTWAREPlay the sample in software (ie. non-accelerated). No other VAM flags may be used together with this flag. + + The following flags enable hardware resource stealing... if the hardware has no available voices, a currently playing buffer will be stopped to make room for the new buffer. Only samples with VAM enabled are considered for termination: + + BASS_VAM_TERM_TIMEIf there are no free hardware voices, the buffer to be terminated will be the one with the least time left to play. + BASS_VAM_TERM_DISTIf there are no free hardware voices, the buffer to be terminated will be one that was loaded/created with the BASS_SAMPLE_MUTEMAX flag and is beyond it's max distance (maxdist). If there are no buffers that match this criteria, then the play call will fail. + BASS_VAM_TERM_PRIOIf there are no free hardware voices, the buffer to be terminated will be the one with the lowest priority. This flag may be used with the TERM_TIME or TERM_DIST flag, if multiple voices have the same priority then the time or distance is used to decide which to terminate. + + + + + + Priority, used with the BASS_VAM_TERM_PRIO flag... 0 (min, default) - 0xFFFFFFFF (max) + + + + + Default constructor. + + + + + Constructor to initialize the members. + + Default playback rate. + Default volume (0-1). + Default pan (-1=left, 0=middle, +1=right). + BASS_SAMPLE_xxx flags (). + Length (in bytes). + Maximum simultaneous playbacks. + Original resolution bits. + Number of channels. + Minimum time gap in milliseconds between creating channels. + BASS_3DMODE_xxx mode (). + Minimum distance. + Maximum distance. + Angle of inside projection cone. + Angle of outside projection cone. + Delta-volume outside the projection cone. + Voice allocation/management flags (BASS_VAM_xxx flags ). + Priority (0=lowest, 0xffffffff=highest). + + + + A description of the record decive info object (driver file name, inputs etc.). + + A description of the record decive info object (driver file name, inputs etc.). + + + + Used with to retrieve information on a channel. + + + A "channel" can be a playing sample (HCHANNEL), a sample stream (HSTREAM), a MOD music (HMUSIC), or a recording (HRECORD). + Each "Channel" function can be used with one or more of these channel types. + The BASS_SAMPLE_SOFTWARE flag indicates whether or not the channel's sample data is being mixed into the final output by the hardware. It does not indicate (in the case of a stream or MOD music) whether the processing required to generate the sample data is being done by the hardware, this processing is always done in software. + BASS supports 8/16/32-bit sample data, so if a WAV file, for example, uses another sample resolution, it'll have to be converted by BASS. The origres member can be used to check what the resolution originally was. + + + + BASS_CHANNELINFO info = new BASS_CHANNELINFO(); + Bass.BASS_ChannelGetInfo(channel, info); // get info + if (info.ctype == BassChannel.BASS_CTYPE_STREAM_MP3) + { + // it's an MP3! + } + + + + + + Default playback rate. + + + + + Number of channels... 1=mono, 2=stereo, etc. + + + + + BASS_SAMPLE/STREAM/MUSIC/SPEAKER flags. A combination of these flags (see ): + + BASS_SAMPLE_8BITSThe channel's resolution is 8-bit. If neither this or the BASS_SAMPLE_FLOAT flags are present, then the channel's resolution is 16-bit. + BASS_SAMPLE_FLOATThe channel's resolution is 32-bit floating-point. + BASS_SAMPLE_LOOPThe channel is looped. + BASS_SAMPLE_3DThe channel has 3D functionality enabled. + BASS_SAMPLE_SOFTWAREThe channel is NOT using hardware mixing... it doesn't benefit from any special hardware interpolation, etc. + BASS_SAMPLE_VAMThe channel is using the DX7 voice allocation and management features. (HCHANNEL only) + BASS_SAMPLE_MUTEMAXThe channel is muted when at (or beyond) it's max distance. (HCHANNEL) + BASS_SAMPLE_FXThe channel has the "with FX flag" DX8 effects implementation enabled. (HSTREAM/HMUSIC) + BASS_STREAM_RESTRATEThe internet file download rate is restricted. (HSTREAM) + BASS_STREAM_BLOCKThe internet file (or "buffered" user file) is streamed in small blocks. (HSTREAM) + BASS_STREAM_AUTOFREEThe channel will automatically be freed when it ends. (HSTREAM/HMUSIC) + BASS_STREAM_DECODEThe channel is a "decoding channel". (HSTREAM/HMUSIC) + BASS_MUSIC_RAMPThe MOD music is using "normal" ramping. (HMUSIC) + BASS_MUSIC_RAMPSThe MOD music is using "sensitive" ramping. (HMUSIC) + BASS_MUSIC_SURROUNDThe MOD music is using surround sound. (HMUSIC) + BASS_MUSIC_SURROUND2The MOD music is using surround sound mode 2. (HMUSIC) + BASS_MUSIC_NONINTERThe MOD music is using non-interpolated mixing. (HMUSIC) + BASS_MUSIC_FT2MODThe MOD music is using FastTracker 2 .MOD playback. (HMUSIC) + BASS_MUSIC_PT1MODThe MOD music is using ProTracker 1 .MOD playback. (HMUSIC) + BASS_MUSIC_POSRESETAll notes will be stopped when seeking in the MOD music. (HMUSIC) + BASS_MUSIC_POSRESETEXAll notes will be stopped and BPM/etc reset when seeking in the MOD music. (HMUSIC) + BASS_MUSIC_STOPBACKThe MOD music will be stopped when a backward jump effect is played. (HMUSIC) + BASS_SPEAKER_xxxSpeaker assignment flags. (HSTREAM/HMUSIC) + BASS_UNICODEA filename, command-line or argument is a Unicode (UTF-16) string. + + Other flags may be supported by add-ons, see the documentation. + + Platform-specific + On Linux/iOS/OSX, the BASS_UNICODE flag may not be present even if it was used in the stream's creation, as BASS will have translated the filename to the native UTF-8 form. On Windows CE, the opposite is true: the BASS_UNICODE flag may be present even if it was not used in the stream's creation, as BASS will have translated the filename to the native UTF-16 form. + + + + + The type of channel it is, which can be one of the following (see ), or another value if it's an add-on format (see the add-on's API). + + BASS_CTYPE_SAMPLESample channel. (HCHANNEL) + BASS_CTYPE_STREAMUser sample stream. This can also be used as a flag to test if the channel is any kind of HSTREAM. + BASS_CTYPE_STREAM_OGGOGG format file stream. + BASS_CTYPE_STREAM_MP1MP1 format file stream. + BASS_CTYPE_STREAM_MP2MP2 format file stream. + BASS_CTYPE_STREAM_MP3MP3 format file stream. + BASS_CTYPE_STREAM_AIFFAudio IFF format stream. + BASS_CTYPE_STREAM_CACoreAudio codec stream. Additional information is avaliable via the tag. + BASS_CTYPE_STREAM_MFMedia Foundation codec stream. Additional format information is avaliable from (BASS_TAG_WAVEFORMAT). + BASS_CTYPE_STREAM_WAVWAVE format flag. This can be used to test if the channel is any kind of WAVE format (LOWORD contains the codec number). + BASS_CTYPE_STREAM_WAV_PCMWAV format file stream, PCM. + BASS_CTYPE_STREAM_WAV_FLOATWAV format file stream, Floating-Point. + BASS_CTYPE_MUSIC_MODMOD format music. This can also be used as a flag to test if the channel is any kind of HMUSIC. + BASS_CTYPE_MUSIC_MTMMTM format music. + BASS_CTYPE_MUSIC_S3MS3M format music. + BASS_CTYPE_MUSIC_XMXM format music. + BASS_CTYPE_MUSIC_ITIT format music. + BASS_CTYPE_MUSIC_MO3MO3 format flag, used in combination with one of the BASS_CTYPE_MUSIC types. + BASS_CTYPE_RECORDRecording channel. (HRECORD) + + Other channel types may be supported by add-ons, see the documentation. + + + + + The original resolution (bits per sample)... 0 = undefined. + + + + + The plugin that is handling the channel... 0 = not using a plugin. + Note this is only available with streams created using the plugin system via the standard BASS stream creation functions, not those created by add-on functions. + Information on the plugin can be retrieved via . + + + + + The sample that is playing on the channel. (HCHANNEL only) + + + + + The filename associated with the channel. (HSTREAM only) + + + + + Default constructor. + + + + + A description of the record decive info object (driver file name, inputs etc.). + + A description of the record decive info object (driver file name, inputs etc.). + + + + Is the channel a decoding channel? + + Checks, that the property contains the BASS_STREAM_DECODE resp. BASS_MUSIC_DECODE flag. + + + + Gets, if the property contains the BASS_SAMPLE_FLOAT resp. BASS_MUSIC_FLOAT flag. + + is returned for floating-point channels - else . + + + + Gets, if the property contains the BASS_SAMPLE_8BITS resp. BASS_MUSIC_8BITS flag. + + is returned for 8-bit channels - else . + + + + Structure used by the 3D functions to describe positions, velocities, and orientations (e.g. or ). + + + The left-handed coordinate system is used. + + Updates the position, velocity and top of the listener: + + BASS_3DVECTOR position = new BASS_3DVECTOR(camera.RealPosition.x, camera.RealPosition.y, camera.RealPosition.z); + BASS_3DVECTOR direction = new BASS_3DVECTOR(camera.RealDirection.x, camera.RealDirection.y, camera.RealDirection.z); + BASS_3DVECTOR up = new BASS_3DVECTOR(-camera.RealUp.x, -camera.RealUp.y, -camera.RealUp.z); + + if (!Bass.BASS_Set3DPosition(position, velocity, direction, up)) + throw new AudioException("Could not set the 3d position of the listener", "listener", Bass.BASS_ErrorGetCode()); + + Bass.BASS_Apply3D(); + + + Dim position As New BASS_3DVECTOR(camera.RealPosition.x, camera.RealPosition.y, camera.RealPosition.z) + Dim direction As New BASS_3DVECTOR(camera.RealDirection.x, camera.RealDirection.y, camera.RealDirection.z) + Dim up As New BASS_3DVECTOR(-camera.RealUp.x, -camera.RealUp.y, -camera.RealUp.z) + + If Not Bass.BASS_Set3DPosition(position, velocity, direction, up) Then + Throw New AudioException("Could not set the 3d position of the listener", "listener", Bass.BASS_ErrorGetCode()) + End If + + Bass.BASS_Apply3D() + + + + + +values=right, -values=left (default=0) + + + + + +values=up, -values=down (default=0) + + + + + +values=front, -values=behind (default=0) + + + + + Default constructor. + + + + + constructor to initialize the members + + X value (+=right, -=left) + Y value (+=up, -=down) + Z value (+=front, -=behind) + + + + The 3D vector as a descriptive string (X=, Y=, Z=). + + The 3D vector as a descriptive string (X=, Y=, Z=) + + + + Used with and to retrieve and set the parameters of a chorus effect. + + + + + Ratio of wet (processed) signal to dry (unprocessed) signal. Must be in the range from 0 (default) through 100 (all wet). + + + + + Percentage by which the delay time is modulated by the low-frequency oscillator, in hundredths of a percentage point. Must be in the range from 0 through 100. The default value is 25. + + + + + Percentage of output signal to feed back into the effect's input, in the range from -99 to 99. The default value is 0. + + + + + Frequency of the LFO, in the range from 0 to 10. The default value is 0. + + + + + Waveform of the LFO... 0 = triangle, 1 = sine. By default, the waveform is a sine. + + + + + Number of milliseconds the input is delayed before it is played back, in the range from 0 to 20. The default value is 0 ms. + + + + + Phase differential between left and right LFOs, one of values. Default is (int)BASSFXPhase.BASS_FX_PHASE_ZERO. + + + + + Default constructor. + + + + + constructor to initialize the members + + Ratio of wet (processed) signal to dry (unprocessed) signal. Must be in the range from 0 through 100 (all wet). + Percentage by which the delay time is modulated by the low-frequency oscillator, in hundredths of a percentage point. Must be in the range from 0 through 100. + Percentage of output signal to feed back into the effect's input, in the range from -99 to 99. + Frequency of the LFO, in the range from 0 to 10. + Waveform of the LFO... 0 = triangle, 1 = sine. + Number of milliseconds the input is delayed before it is played back, in the range from 0 to 20. + Phase differential between left and right LFOs (see ). + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Used with and to retrieve and set the parameters of a compression effect. + + + + + Output gain of signal in dB after compression, in the range from -60 to 60. The default value is 0 dB. + + + + + Time in ms before compression reaches its full value, in the range from 0.01 to 500. The default value is 10 ms. + + + + + Time (speed) in ms at which compression is stopped after input drops below fThreshold, in the range from 50 to 3000. The default value is 200 ms. + + + + + Point at which compression begins, in dB, in the range from -60 to 0. The default value is -20 dB. + + + + + Compression ratio, in the range from 1 to 100. The default value is 3, which means 3:1 compression. + + + + + Time in ms after fThreshold is reached before attack phase is started, in milliseconds, in the range from 0 to 4. The default value is 4 ms. + + + + + Default constructor. + + + + + constructor to already set the members + + Output gain of signal after compression, in the range from -60 to 60. + Time before compression reaches its full value, in the range from 0.01 to 500. + Speed at which compression is stopped after input drops below fThreshold, in the range from 50 to 3000. + Point at which compression begins, in decibels, in the range from -60 to 0. + Compression ratio, in the range from 1 to 100. + Time after lThreshold is reached before attack phase is started, in milliseconds, in the range from 0 to 4. + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Used with and to retrieve and set the parameters of a distortion effect. + + + + + Amount of signal change after distortion, in the range from -60 through 0. The default value is 0 dB. + + + + + Percentage of distortion intensity, in the range in the range from 0 through 100. The default value is 50 percent. + + + + + Center frequency of harmonic content addition, in the range from 100 through 8000. The default value is 4000 Hz. + + + + + Width of frequency band that determines range of harmonic content addition, in the range from 100 through 8000. The default value is 4000 Hz. + + + + + Filter cutoff for high-frequency harmonics attenuation, in the range from 100 through 8000. The default value is 4000 Hz. + + + + + Default constructor. + + + + + constructor already setting the members + + Amount of signal change after distortion, in the range from -60 through 0. + Percentage of distortion intensity, in the range in the range from 0 through 100. + Center frequency of harmonic content addition, in the range from 100 through 8000. + Width of frequency band that determines range of harmonic content addition, in the range from 100 through 8000. + Filter cutoff for high-frequency harmonics attenuation, in the range from 100 through 8000. + + + + Sets the instance members to a preset. + + + + + Used with and to retrieve and set the parameters of a echo effect. + + + + + Ratio of wet (processed) signal to dry (unprocessed) signal. Must be in the range from 0 (default) through 100 (all wet). + + + + + Percentage of output fed back into input, in the range from 0 through 100. The default value is 0. + + + + + Delay for left channel, in milliseconds, in the range from 1 through 2000. The default value is 333 ms. + + + + + Delay for right channel, in milliseconds, in the range from 1 through 2000. The default value is 333 ms. + + + + + Value that specifies whether to swap left and right delays with each successive echo. The default value is , meaning no swap. + + + + + Default constructor. + + + + + constructor already setting the members + + Ratio of wet (processed) signal to dry (unprocessed) signal. Must be in the range from 0 through 100 (all wet). + Percentage of output fed back into input, in the range from 0 through 100. + Delay for left channel, in milliseconds, in the range from 1 through 2000. + Delay for right channel, in milliseconds, in the range from 1 through 2000. + Value that specifies whether to swap left and right delays with each successive echo. + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Used with and to retrieve and set the parameters of a flanger effect. + + + + + Ratio of wet (processed) signal to dry (unprocessed) signal. Must be in the range from 0 (default) through 100 (all wet). + + + + + Percentage by which the delay time is modulated by the low-frequency oscillator (LFO), in hundredths of a percentage point. Must be in the range from 0 through 100. The default value is 25. + + + + + Percentage of output signal to feed back into the effect's input, in the range from -99 to 99. The default value is 0. + + + + + Frequency of the LFO, in the range from 0 to 10. The default value is 0. + + + + + Waveform of the LFO... 0 = triangle, 1 = sine. By default, the waveform is a sine. + + + + + Number of milliseconds the input is delayed before it is played back, in the range from 0 to 4. The default value is 0 ms. + + + + + Phase differential between left and right LFOs, one of the values. Default (int)BASSFXPhase.BASS_FX_PHASE_ZERO. + + + + + Default constructor. + + + + + constructor already setting the members + + Ratio of wet (processed) signal to dry (unprocessed) signal. Must be in the range from 0 through 100 (all wet). + Percentage by which the delay time is modulated by the low-frequency oscillator (LFO), in hundredths of a percentage point. Must be in the range from 0 through 100. + Percentage of output signal to feed back into the effect's input, in the range from -99 to 99. + Frequency of the LFO, in the range from 0 to 10. + Waveform of the LFO... 0 = triangle, 1 = sine. + Number of milliseconds the input is delayed before it is played back, in the range from 0 to 4. + Phase differential between left and right LFOs, one of . + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Used with and to retrieve and set the parameters of a gargle effect. + + + + + Rate of modulation, in Hertz. Must be in the range from 1 through 1000. Default 500 Hz. + + + + + Shape of the modulation wave... 0 = triangle, 1 = square (default). + + + + + Default constructor. + + + + + constructor already setting the members + + Rate of modulation, in Hertz. Must be in the range from 1 through 1000. + Shape of the modulation wave... 0 = triangle, 1 = square. + + + + Sets the instance members to a preset. + + + + + Used with and to retrieve and set the parameters of an I3DL2 (Interactive 3D Audio Level 2) reverberation effect. + + + + + Attenuation of the room effect, in millibels (mB), in the range from -10000 to 0. The default value is -1000 mB. + + + + + Attenuation of the room high-frequency effect, in mB, in the range from -10000 to 0. The default value is 0 mB. + + + + + Rolloff factor for the reflected signals, in the range from 0 to 10. The default value is 0.0. + + + + + Decay time, in seconds, in the range from 0.1 to 20. The default value is 1.49 second. + + + + + Ratio of the decay time at high frequencies to the decay time at low frequencies, in the range from 0.1 to 2. The default value is 0.83. + + + + + Attenuation of early reflections relative to lRoom, in mB, in the range from -10000 to 1000. The default value is -2602 mB. + + + + + Delay time of the first reflection relative to the direct path, in seconds, in the range from 0 to 0.3. The default value is 0.007 seconds. + + + + + Attenuation of late reverberation relative to lRoom, in mB, in the range from -10000 to 2000. The default value is 200 mB. + + + + + Time limit between the early reflections and the late reverberation relative to the time of the first reflection, in seconds, in the range from 0 to 0.1. The default value is 0.011 seconds. + + + + + Echo density in the late reverberation decay, in percent, in the range from 0 to 100. The default value is 100.0 percent. + + + + + Modal density in the late reverberation decay, in percent, in the range from 0 to 100. The default value is 100.0 percent. + + + + + Reference high frequency, in hertz, in the range from 20 to 20000. The default value is 5000.0 Hz. + + + + + Default constructor. + + + + + constructor already setting the members + + Attenuation of the room effect, in millibels (mB), in the range from -10000 to 0. + Attenuation of the room high-frequency effect, in mB, in the range from -10000 to 0. + Rolloff factor for the reflected signals, in the range from 0 to 10. + Decay time, in seconds, in the range from 0.1 to 20. + Ratio of the decay time at high frequencies to the decay time at low frequencies, in the range from 0.1 to 2. + Attenuation of early reflections relative to lRoom, in mB, in the range from -10000 to 1000. + Delay time of the first reflection relative to the direct path, in seconds, in the range from 0 to 0.3. + Attenuation of late reverberation relative to lRoom, in mB, in the range from -10000 to 2000. + Time limit between the early reflections and the late reverberation relative to the time of the first reflection, in seconds, in the range from 0 to 0.1. + Echo density in the late reverberation decay, in percent, in the range from 0 to 100. + Modal density in the late reverberation decay, in percent, in the range from 0 to 100. + Reference high frequency, in hertz, in the range from 20 to 20000. + + + + Sets the instance members to a preset. + + + + + Used with and to retrieve and set the parameters of a parametric equalizer effect. + + + Platform-specific + On Windows, fCenter must be in the range of 80 to 16000, and not exceed one-third of the channel's sample rate. On other platforms, the range is above 0 Hz and below half the channel's sample rate. + + + Setting up a 3-band EQ: + + private int[] _fxEQ = {0, 0, 0}; + ... + // 3-band EQ + BASS_DX8_PARAMEQ eq = new BASS_DX8_PARAMEQ(); + _fxEQ[0] = Bass.BASS_ChannelSetFX(_stream, BASSFXType.BASS_FX_DX8_PARAMEQ, 0); + _fxEQ[1] = Bass.BASS_ChannelSetFX(_stream, BASSFXType.BASS_FX_DX8_PARAMEQ, 0); + _fxEQ[2] = Bass.BASS_ChannelSetFX(_stream, BASSFXType.BASS_FX_DX8_PARAMEQ, 0); + eq.fBandwidth = 18f; + eq.fCenter = 100f; + eq.fGain = 0f; + Bass.BASS_FXSetParameters(_fxEQ[0], eq); + eq.fCenter = 1000f; + Bass.BASS_FXSetParameters(_fxEQ[1], eq); + eq.fCenter = 8000f; + Bass.BASS_FXSetParameters(_fxEQ[2], eq); + ... + private void UpdateEQ(int band, float gain) + { + BASS_DX8_PARAMEQ eq = new BASS_DX8_PARAMEQ(); + if (Bass.BASS_FXGetParameters(_fxEQ[band], eq)) + { + eq.fGain = gain; + Bass.BASS_FXSetParameters(_fxEQ[band], eq); + } + } + + + Private _fxEQ As Integer() = {0, 0, 0} + ... + ' 3-band EQ + Dim eq As New BASS_DX8_PARAMEQ() + _fxEQ(0) = Bass.BASS_ChannelSetFX(_stream, BASSFXType.BASS_FX_DX8_PARAMEQ, 0) + _fxEQ(1) = Bass.BASS_ChannelSetFX(_stream, BASSFXType.BASS_FX_DX8_PARAMEQ, 0) + _fxEQ(2) = Bass.BASS_ChannelSetFX(_stream, BASSFXType.BASS_FX_DX8_PARAMEQ, 0) + eq.fBandwidth = 18F + eq.fCenter = 100F + Bass.BASS_FXSetParameters(_fxEQ(0), eq) + eq.fCenter = 1000F + Bass.BASS_FXSetParameters(_fxEQ(1), eq) + eq.fCenter = 8000F + Bass.BASS_FXSetParameters(_fxEQ(2), eq) + ... + Private Sub UpdateEQ(band As Integer, gain As Single) + Dim eq As New BASS_DX8_PARAMEQ() + If Bass.BASS_FXGetParameters(_fxEQ(band), eq) Then + eq.fGain = gain + Bass.BASS_FXSetParameters(_fxEQ(band), eq) + End If + End Sub + + + + + + Center frequency, in hertz, in the range from 80 to 16000. This value cannot exceed one-third of the frequency of the channel. Default 100 Hz. + + + + + Bandwidth, in semitones, in the range from 1 to 36. Default 18 semitones. + + + + + Gain, in the range from -15 to 15. Default 0 dB. + + + + + Default constructor. + + + + + constructor already setting the members + + Center frequency, in hertz, in the range from 80 to 16000. This value cannot exceed one-third of the frequency of the channel. + Bandwidth, in semitones, in the range from 1 to 36. + Gain in dB, in the range from -15 to 15. + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Sets the instance members to a preset. + + + + + Used with and to retrieve and set the parameters of a reverb effect. + + + + + Input gain of signal, in decibels (dB), in the range from -96 through 0. The default value is 0 dB. + + + + + Reverb mix, in dB, in the range from -96 through 0. The default value is 0 dB. + + + + + Reverb time, in milliseconds, in the range from 0.001 through 3000. The default value is 1000. + + + + + In the range from 0.001 through 0.999. The default value is 0.001. + + + + + Default constructor. + + + + + constructor already setting the members + + Input gain of signal, in decibels (dB), in the range from -96 through 0. + Reverb mix, in dB, in the range from -96 through 0. + Reverb time, in milliseconds, in the range from 0.001 through 3000. + In the range from 0.001 through 0.999. + + + + Sets the instance members to a preset. + + + + + TAG structure of an ID3v1 block to be used with . + + Use 'Marshal.PtrToStructure' to convert a tag pointer to this structure. + + + IntPtr p = Bass.BASS_ChannelGetTags(stream, BASSTag.BASS_TAG_ID3); + if (p != IntPtr.Zero) + { + BASS_TAG_ID3 id3 = (BASS_TAG_ID3)Marshal.PtrToStructure(p, typeof(BASS_TAG_ID3)); + ... + } + + + Dim p As IntPtr = Bass.BASS_ChannelGetTags(stream, BASSTag.BASS_TAG_ID3) + If p <> IntPtr.Zero Then + Dim id3 As BASS_TAG_ID3 = DirectCast(Marshal.PtrToStructure(p, GetType(BASS_TAG_ID3)), BASS_TAG_ID3) + ... + End If + + + + + + The Dummy 0. + + + + + The track number. + + + + + The genre id. + + + + + The id string (should be 'TAG'). + + + + + The title string (max. 30 characters). + + + + + The artist string (max. 30 characters). + + + + + The album string (max. 30 characters). + + + + + The year string (max. 4 characters). + + + + + The comment string (max. 28 characters). + + + + + TAG structure of a BWF BEXT block to be used with . + + Use 'Marshal.PtrToStructure' to convert a tag pointer to this structure. + + + IntPtr p = Bass.BASS_ChannelGetTags(stream, BASSTag.BASS_TAG_RIFF_BEXT); + if (p != IntPtr.Zero) + { + BASS_TAG_BEXT bext = (BASS_TAG_BEXT)Marshal.PtrToStructure(p, typeof(BASS_TAG_BEXT)); + string codingHist = bext.GetCodingHistory(p); + ... + } + + + Dim p As IntPtr = Bass.BASS_ChannelGetTags(stream, BASSTag.BASS_TAG_RIFF_BEXT) + If p <> IntPtr.Zero Then + Dim bext As BASS_TAG_BEXT = DirectCast(Marshal.PtrToStructure(p, GetType(BASS_TAG_BEXT)), BASS_TAG_BEXT) + Dim codingHist As String = bext.GetCodingHistory(p) + ... + End If + + + + + + First sample count since midnight (little-endian). + + + + + The BWF version (little-endian) + + + + + Reserved for future use. + + + + + The description field of the TAG structure. + + The description field of the TAG structure. + + + + Returns the coding history for a given BASS_TAG_RIFF_BEXT tag pointer. + + The bext tag pointer as returned by . + The coding history string or (if the tag pointer is not valid). + + + + Returns a byte array containing the data of this instance plus the given . + + The new (total) coding history string to add to this structure. + The byte array containing the instance data plus the given . + This method might be used to create a raw BEXT data chunk (e.g. to be used with the method). + + + + The description or title (max. 256 characters). + + + The description might contain a short and/or a long + description. If this field is splitted (by a ";") the first + entry will contain the short description and the + second entry will contain the long description. + + + + + The name of the originator or artist (max. 32 characters). + + + + + The reference of the originator or encoded by (max. 32 characters). + + + + + The date of creation (max. 10 characters, in format yyyy-mm-dd). + + + + + The time of creation (max. 10 characters, in format hh:mm:ss). + + + + + The SMPTE UMID as a hex string in the format 'XX XX XX... XX'. + + + + + TAG structure of a BWF CART block to be used with . + + Use 'Marshal.PtrToStructure' to convert a tag pointer to this structure. + + + IntPtr p = Bass.BASS_ChannelGetTags(stream, BASSTag.BASS_TAG_RIFF_CART); + if (p != IntPtr.Zero) + { + BASS_TAG_CART cart = (BASS_TAG_CART)Marshal.PtrToStructure(p, typeof(BASS_TAG_CART)); + string tagText = cart.GetTagText(p); + ... + } + + + Dim p As IntPtr = Bass.BASS_ChannelGetTags(stream, BASSTag.BASS_TAG_RIFF_CART) + If p <> IntPtr.Zero Then + Dim cart As BASS_TAG_CART = DirectCast(Marshal.PtrToStructure(p, GetType(BASS_TAG_CART)), BASS_TAG_CART) + Dim tagText As String = cart.GetTagText(p) + ... + End If + + + + + + Reserved for future use (276 bytes!). + + + + + The description field of the TAG structure. + + The description field of the TAG structure (Artist - Title). + + + + Returns the free form text for scripts or tags for a given BASS_TAG_RIFF_CART tag pointer. + + The cart tag pointer as returned by . + The tag text string or (if the tag pointer is not valid). + + The tag text is a non-restricted ASCII characters containing a collection of strings each + terminated by CRLF. This text may be system- or user- defined + descriptive text for the sound, such as live tag, script information, descriptive + text special instructions, and so on. + + + + + Returns a byte array containing the data of this instance plus the given . + + The new (total) tag text string to add to this structure. + The byte array containing the instance data plus the given . + This method might be used to create a raw CART data chunk (e.g. to be used with the method). + + + + The version of the cart data structure (4 characters). + + + The first two numbers shall give the major release level (with leading 0) from 00 to 99 + and the last two shall give the revision level (with leading 0) in the range of 00 to + 99. The version number of the cart data structure as described in this + document shall be version 1.01, and thus is represented by the string 0101. + + + + + The title of the cut (max. 64 characters). + + + The title should be a descriptive summary of the audio contents of the file, and may be + used as an entry into a table of contents, and so on. Applications that do not + support a 64-character title may truncate the field as needed. + + + + + The artist of the cut (max. 64 characters). + + + ASCII string, 64-characters or less, holding the artist or creator name for the audio cut. + + + + + The cut number identification (max. 64 characters). + + + ASCII string, 64-characters or less, representing the cut number, or unique cut + key. The string shall be left justified. Some consumer systems can have + restricted cut number lengths or allowable character set. These applications + should provide some means of synthesizing a usable cut identifier if it has such + restrictions. + + + + + The client identification (max. 64 characters). + + + ASCII string, 64-characters or less, holding a client or customer identification or name. + + + + + The category identification (e.g. PSA, NEWS etc. - max. 64 characters). + + + ASCII string, 64-characters or less, holding a category name. The category + name may be application dependent. Applications should use common category names. E.g.: + + ALL, BED, BEDS, BIT, BITS, COM, COMM, CON, CONT, DAY, EB, EFX, FIL, FILL, ID, INT, INTR, JIN, JING, LIN, LINE, LOG, LOGO, MAG, MAGI, MUS, MUSC, NET, NETW, NEW, NEWS, PRO, PROM, PSA, SEG, SHW, SHOW, SND, SPO, SPOT, SPR, SPRT, STG, STAG, STK, STAK, SWP, SWEP, TST, TEST, TMP, TEMP. + + + + + + The classification or auxiliary key (max. 64 characters). + + + ASCII string, 64-characters or less, holding a classification key. This key may + be used for general classification, selection or sorting based on language, + locale or other similar applications. + + + + + The out cue text (max. 64 characters). + + + ASCII string, 64-characters or less, holding the optional out cue phrase to be + displayed when the cut is being played. This shall be a user readable cue + string. + + + + + The start date of the cut (max. 10 characters, in format yyyy-mm-dd). + + + An ASCII date string of the form yyyy-mm-dd, such as 1998-12-25, holding the + start date. Any valid date can be used. To signify an immediate start date, use + '1900-01-01.' + + + + + The start time of cut (max. 10 characters, in format hh:mm:ss). + + + An ASCII time string of the form hh:mm:ss, such as 12:31:45, representing the + 24 hour time-of-day for the start time on the assigned . If blank, + assume 00:00:00. + + + + + The end date of the cut (max. 10 characters, in format yyyy-mm-dd). + + + As in start date, but shall indicate the date after which the sequence will no + longer be active. If the sequence is to run forever, the date shall be 9999-12-31. + There shall be no default for this field. + + + + + The end time of cut (max. 10 characters, in format hh:mm:ss). + + + This code shall indicate the time of day on the appointed end date after which + the sequence becomes inactive. If blank, applications shall assume an end + time of 23:59:59. + + + + + The name of the vendor or application (max. 64 characters). + + + An ASCII string, 64 characters or less, containing the vendor name, product + name or both of the program or application that produced the WAVE file with + this cart chunk. + + + + + The version of the producer application (max. 64 characters). + + + An ASCII string, 64 characters or less, containing the version of the program + or applications that produced the WAVE file containing the cart chunk. + Because this string is informational only, the application may represent the + version in any convenient format. + + + + + A user defined text (max. 64 characters). + + + An ASCII string, 64 characters or less, whose use and contents may be + defined by the user of the system. + + + + + Sample value for 0 dB reference (signed Int32). + + + A 32-bit signed (2’s complement) integer word that shall hold the sample value + of the 0-dB reference level for the originating system. This reference can + facilitate scaling and metering consistency across disparate systems. As an + example, a 16-bit linear PCM system that has its meters calibrated as 0 + corresponding to maximum signed digital value shall have the value set to + 32768 (800016). + + The peak value shall be the absolute value of the largest sample value possible + before saturation. In the example given, that of a 16-bit linear system using 2’s + complement notation, the range of allowable values is -32768 to 32767, thus the + maximum peak value is 32768 in the example given. + + + + + + 1st timer usage ID (4 characters). + + + Timer types, along with their FOURCC identification should be according to the following table. + The interpretation and behavior of systems on encountering timer information may be site dependent, implementation dependent, or both: + SEG: Segue timer (start-end, enumerated, multiples) + AUD: Audio boundary (start-end) + INT: Introduction (start-end, enumerated, multiples) + OUT: Epilog (start-end, enumerated, multiples) + SEC: Secondary (start-end, enumerated, multiples) + TER: Tertiary (start-end, enumerated, multiples) + MRK: Generic marker (multiplesenumerated, ) + EOD: End-of-data (multiples) + Timers may be qualified in one of three ways: + a) as start or end timers, by appending a lower case ASCII letter s for a start timer or a lower case ASCII + letter e for an end timer; for example, the timer identification AUDs designates the start of audio following + silence, while AUDe designates the end of the audio segment; + b) as enumerated timers, by appending an ASCII numeric character; for example, SEC1 may be designated + secondary timer number 1, SEC2 may be secondary number 2, and so on; + c) as multiple timers, by having multiple instances of the same timer ID; one may have, for example, + multiple instances of MRK. + Each application may prioritize the order of the timers. + + If a timer is not used, or is not set, its usage identifier should be set to all zero characters (0x00000000). + + + + + + 1st timer value in samples from head (unsigned Int32). + + + The time units shall be in sample periods at the sampling frequency of the associated audio data and + shall be referenced to the first sample of the audio data. + + The timer range shall be 232 or 4,294,967,295 sample periods. These periods + allow timer ranges at a sampling frequency of 48 kHz, for example, to extend + beyond 24 h (24:51:18). + These timers may be used to activate events in the cart system. + + + If a timer is not used, or is not set, its timer value set to 0. + + Note: This member is actually an unsigned value - but due to the CLS-compliant rule it must have been defined as a signed int. + + + + + 2nd timer usage ID (4 characters). + + See for details. + + + + 2nd timer value in samples from head (unsigned Int32). + + See for details. + + + + 3rd timer usage ID (4 characters). + + See for details. + + + + 3rd timer value in samples from head (unsigned Int32). + + See for details. + + + + 4th timer usage ID (4 characters). + + See for details. + + + + 4th timer value in samples from head (unsigned Int32). + + See for details. + + + + 5th timer usage ID (4 characters). + + See for details. + + + + 5th timer value in samples from head (unsigned Int32). + + See for details. + + + + 6th timer usage ID (4 characters). + + See for details. + + + + 6th timer value in samples from head (unsigned Int32). + + See for details. + + + + 7th timer usage ID (4 characters). + + See for details. + + + + 7th timer value in samples from head (unsigned Int32). + + See for details. + + + + 8th timer usage ID (4 characters). + + See for details. + + + + 8th timer value in samples from head (unsigned Int32). + + See for details. + + + + Uniform resource locator (max. 1024 characters). + + + An ASCII string, 1024-characters or less, representing a universal resource + locator (URL) referencing or referenced by the audio program. + + + + + TAG structure of the Apple CoreAudio codec information structure as returned by . + + A list of file and audio data format identifiers is available from Apple, . + Additional formats may be available via third-party codecs. + + + + The file format identifier. + + + + + The audio format identifier. + + + + + The description of the audio file format. + + + + + Default constructor. + + + + + Constructor to create an instance from the return value. + + The pointer as returned by . + + + + A description of the decive info object (name). + + A description of the decive info object (name). + + + + The file format. + + + + + The audio format. + + + + + The description of the audio file format. + + + + + APE binary tag structure as returned by using the flag. + + + + When calling with the flag make sure to add the index number of the binray tag to get. + E.g. call: Bass.BASS_ChannelGetTags( stream, (BASSTag)(BASSTag.BASS_TAG_APE_BINARY + 1) ) to get the 2nd binary tag. + + + + Read all APE binary tags: + + BASS_TAG_APE_BINARY apeBin; + for (int n = 0; (apeBin = BASS_TAG_APE_BINARY.GetTag(stream, n)) != null; n++) + { + Console.WriteLine(apeBin); + // access the binary data + byte[] data = apeBin.Data; + } + + + Dim apeBin As BASS_TAG_APE_BINARY + Dim n As Integer + For n = 0 To (apeBin BASS_TAG_APE_BINARY.GetTag(stream, n)) <> Nothing Step n + 1 + Console.WriteLine(apeBin) + ' access the binary data + Dim data() As Byte = apeBin.Data + Next + + + + + + Returns the Key of the binary tag. + + Returns the Key of the binary tag. + + + + Hidden default constructor. + + + + + Gets a BASS_TAG_APE_BINARY tag from a given channel handle. + + The channel handle...a HMUSIC or HSTREAM. + The zero-based index of the binary tag to get. + Returns a instance if the could be retrieved successfully - else is returned. + This method internally calles to retrieve the BASS_TAG_APE_BINARY tag. + + Read all APE binary tags: + + BASS_TAG_APE_BINARY apeBin; + for (int n = 0; (apeBin = BASS_TAG_APE_BINARY.GetTag(stream, n)) != null; n++) + { + Console.WriteLine(apeBin); + // access the binary data + byte[] data = apeBin.Data; + } + + + Dim apeBin As BASS_TAG_APE_BINARY + Dim n As Integer + For n = 0 To (apeBin BASS_TAG_APE_BINARY.GetTag(stream, n)) <> Nothing Step n + 1 + Console.WriteLine(apeBin) + ' access the binary data + Dim data() As Byte = apeBin.Data + Next + + + + + + Creates an instance of the class from a pointer. + + The pointer to a structure (e.g. as returned by using the flag). + The created instance of the class on success - else is returned. + + + + The name of the tag. + + + + + The binary tag data. + + + + + The size of in bytes. + + + + + FLAC picture tag structure as returned by using the flag. + + + The width, height, depth, and colors members may be empty (0) so should not be depended on. That information can be obtained from the picture data itself. + Use the static method to get the FLAC picture tag from a given channel handle. + + When calling with the flag make sure to add the index number of the picture to get. + E.g. call: Bass.BASS_ChannelGetTags( stream, (BASSTag)(BASSTag.BASS_TAG_FLAC_PICTURE + 1) ) to get the 2nd picture. + + + + Read all FLAC picture tags: + + BASS_TAG_FLAC_PICTURE flacPic; + for (int n = 0; (flacPic = BASS_TAG_FLAC_PICTURE.GetTag(stream, n)) != null; n++) + { + Console.WriteLine(flacPic); + // access the image picture + Image img = flacPic.Picture; + // access the raw image data + byte[] data = flacPic.Data; + } + + + Dim flacPic As BASS_TAG_FLAC_PICTURE + Dim n As Integer + For n = 0 To (flacPic BASS_TAG_FLAC_PICTURE.GetTag(stream, n)) <> Nothing Step n + 1 + Console.WriteLine(flacPic) + ' access the image picture + Dim img As Image = flacPic.Picture + ' access the raw image data + Dim data() As Byte = flacPic.Data + Next + + + + + + The picture type, according to the ID3v2 "APIC" frame specification: see www.id3.org for details. + + + + + Returns the description and mime type of the picture. + + Returns e.g. "CoverArt (image/jpeg)". + + + + Hidden default constructor. + + + + + Gets a BASS_TAG_FLAC_PICTURE tag from a given channel handle. + + The channel handle...a HMUSIC or HSTREAM. + The zero-based picture index to get. + Returns a instance if the could be retrieved successfully - else is returned. + This method internally calles to retrieve the BASS_TAG_FLAC_PICTURE tag. + + Read all FLAC picture tags: + + BASS_TAG_FLAC_PICTURE flacPic; + for (int n = 0; (flacPic = BASS_TAG_FLAC_PICTURE.GetTag(stream, n)) != null; n++) + { + Console.WriteLine(flacPic); + // access the image picture + Image img = flacPic.Picture; + // access the raw image data + byte[] data = flacPic.Data; + } + + + Dim flacPic As BASS_TAG_FLAC_PICTURE + Dim n As Integer + For n = 0 To (flacPic BASS_TAG_FLAC_PICTURE.GetTag(stream, n)) <> Nothing Step n + 1 + Console.WriteLine(flacPic) + ' access the image picture + Dim img As Image = flacPic.Picture + ' access the raw image data + Dim data() As Byte = flacPic.Data + Next + + + + + + Creates an instance of the class from a pointer. + + The pointer to a structure (e.g. as returned by using the flag). + The created instance of the class on success - else is returned. + + + + The MIME type string. This may be "-->" to signify that data contains a URL of the picture rather than the picture data itself. + + + + + A description string of the picture. + + + + + The width in pixels. + + + + + The height in pixels. + + + + + The colour depth in bits-per-pixel. + + + + + The number of colours used for indexed-colour pictures (eg. GIF). + + + + + The size of in bytes. + + + + + The picture data. + + + + + The picture image. + + + + + Returns the image URL, if the type is "-->" - else is returned. + + + + + FLAC cuesheet tag structure as returned by using the flag. + + + Further details can be found in the FLAC format specification, here: flac.sourceforge.net. + Use the static method to get the FLAC cuesheet tag from a given channel handle. + + + Read the FLAC cuesheet tag: + + BASS_TAG_FLAC_CUE cuesheet = BASS_TAG_FLAC_CUE.GetTag(stream); + + + Dim cuesheet As BASS_TAG_FLAC_CUE = BASS_TAG_FLAC_CUE.GetTag(stream) + + + + + + Hidden default constructor. + + + + + Gets a BASS_TAG_FLAC_CUE tag from a given channel handle. + + The channel handle...a HMUSIC or HSTREAM. + Returns a instance if the could be retrieved successfully - else is returned. + This method internally calles to retrieve the BASS_TAG_FLAC_CUE tag. + + Read the FLAC cuesheet tag: + + BASS_TAG_FLAC_CUE cuesheet = BASS_TAG_FLAC_CUE.GetTag(stream); + + + Dim cuesheet As BASS_TAG_FLAC_CUE = BASS_TAG_FLAC_CUE.GetTag(stream) + + + + + + Creates an instance of the class from a pointer. + + The pointer to a structure (e.g. as returned by using the flag). + The created instance of the class on success - else is returned. + + + + The media catalog number. + + + + + The number of lead-in samples. + + + + + The cuesheet corresponds to a CD? + + + + + The number of tracks. + + + + + The array of tracks (or ). + + + + + FLAC cuesheet tag track structure as returned by the member. + + + Read the FLAC cuesheet tag: + + BASS_TAG_FLAC_CUE cuesheet = BASS_TAG_FLAC_CUE.GetTag(stream); + + + Dim cuesheet As BASS_TAG_FLAC_CUE = BASS_TAG_FLAC_CUE.GetTag(stream) + + + + + + Hidden default constructor. + + + + + Track offset in samples. + + + + + The track number. + + + + + The International Standard Recording Code. + + + + + The track flags. + + Any combination of the following flags: + + TAG_FLAC_CUE_TRACK_DATANon-audio. + TAG_FLAC_CUE_TRACK_PREPre-emphasis. + + + + + + The number of . + + + + + The array of indexes (or ). + + + + + The possible cuesheet track type . + + + + + Audio (default). + + + + + Non-audio. + + + + + Pre-emphasis. + + + + + FLAC cuesheet tag track index structure as returned by the member. + + + Read the FLAC cuesheet tag: + + BASS_TAG_FLAC_CUE cuesheet = BASS_TAG_FLAC_CUE.GetTag(stream); + + + Dim cuesheet As BASS_TAG_FLAC_CUE = BASS_TAG_FLAC_CUE.GetTag(stream) + + + + + + Hidden default constructor. + + + + + Index offset in samples relative to the track offset. + + + + + The index number. + + + + + The WAVEFORMATEX structure defines the format of waveform-audio data. + Only format information common to all waveform-audio data formats is included in this structure. + For formats that require additional information, this structure is included as the first member in another structure, along with the additional information. + See for details. + + + + + Waveform-audio format type (see ). Format tags are registered with Microsoft Corporation for many compression algorithms. + A complete list of format tags can be found in the Mmreg.h header file. + For one- or two-channel PCM data, this value should be WAVE_FORMAT_PCM. + Default = 1 (WAVE_FORMAT_PCM) + + + + + Number of channels in the waveform-audio data. Monaural data uses one + channel and stereo data uses two channels. + Default = 2 + + + + + Sample rate, in samples per second (hertz), that each channel should + be played or recorded. If wFormatTag is WAVE_FORMAT_PCM, then common + values for nSamplesPerSec are 8.0 kHz, 11.025 kHz, 22.05 kHz, and + 44.1 kHz. For non-PCM formats, this member must be computed according + to the manufacturer's specification of the format tag. + Default = 44100 + + + + + In most cases, this member contains the required average data-transfer rate, + in bytes per second, for the format tag. If wFormatTag is WAVE_FORMAT_PCM, + nAvgBytesPerSec should be equal to the product of nSamplesPerSec and nBlockAlign. + For non-PCM formats, this member must be computed according to the manufacturer's + specification of the format tag. + When the Windows Media Audio 9 Codec is in quality-based variable-bit-rate mode, + the high-order bytes of this member are set to 0x7fffff and the low-order byte is set to a value + from one through 100 which indicates the quality level. + Typical Calculation: nSamplesPerSec * nBlockAlign + Default = 176400 + + + + + Block alignment, in bytes. The block alignment is the minimum atomic unit + of data for the wFormatTag format type. If wFormatTag is WAVE_FORMAT_PCM, + nBlockAlign should be equal to the product of nChannels and wBitsPerSample + divided by 8 (bits per byte). For non-PCM formats, this member must be + computed according to the manufacturer's specification of the format tag. + Playback and record software must process a multiple of nBlockAlign bytes + of data at a time. Data written and read from a device must always start + at the beginning of a block. For example, it is illegal to start playback + of PCM data in the middle of a sample (that is, on a non-block-aligned boundary). + Typical Calculation: nChannels * (wBitsPerSample / 8) + Default = 4 + + + + + Bits per sample for the wFormatTag format type. If wFormatTag is + WAVE_FORMAT_PCM, then wBitsPerSample should be equal to 8, 16 or 32. For + non-PCM formats, this member must be set according to the manufacturer's + specification of the format tag. Some compression schemes cannot define + a value for wBitsPerSample, so this member can be zero. + Default = 16 + + + + + Size, in bytes, of extra format information appended to the end of the WAVEFORMATEX structure. + This information can be used by non-PCM formats to store extra attributes for the wFormatTag. + If no extra information is required by the wFormatTag, this member must be set to zero. + For WAVE_FORMAT_PCM formats (and only WAVE_FORMAT_PCM formats), this member is ignored. + Default = 0 + + + + + Default Constructor. + + + + + Creates an instance setting the members to certain values. + + Waveform-audio format type (see ). + Number of channels in the waveform-audio data. + Sample rate, in samples per second (hertz), that each channel should be played or recorded. + Bits per sample for the wFormatTag format type (e.g. 8, 16 or 32). + Size, in bytes, of extra format information appended to the end of the WAVEFORMATEX structure. + + + + Returns a description string for the instance members. + + Returns a description string for the instance members (wFormatTag, res, nSamplesPerSec, chans). + + + + The WAVEFORMATEXT is a specialized and generic format structure. It contains the WAVEFORMATEX structure and define the format of any Media Foundation audio data. + Only format information common to all MF audio data formats are included in this structure. + For formats that require additional information, this structure has an additional byte[] keeping the additional information. + + + + + The structure that specifies the basic format. + + + + + Extra format information is appended to the end of the WAVEFORMATEX structure in this array. + This information can be used by non-PCM formats to store extra attributes for the wFormatTag. + If no extra information is required by the wFormatTag, this member should be set to zero. + For WAVE_FORMAT_PCM formats (and only WAVE_FORMAT_PCM formats), this member is ignored. + + + + + Creates an instance of a generic audio codec format with a given total length. + + The total lenght of the format structure including the extension data. + + + + + + Creates an instance of a generic audio codec format from the given format buffer pointer. + + A pointer to an audio codec format structure as e.g. returned by using the flag. + + + + Returns a description string for the instance members. + + Returns a description string for the instance members (wFormatTag, res, nSamplesPerSec, chans). + + + + Returns the total length of this instance. + + + + + User stream writing callback delegate (to be used with ). + + The stream that needs writing. + The pointer to the buffer to write the sample data in. The sample data must be written in standard Windows PCM format - 8-bit samples are unsigned, 16-bit samples are signed, 32-bit floating-point samples range from -1 to 1. + The number of bytes to write. + The user instance data given when was called. + The number of bytes written by the function, optionally using the BASS_STREAMPROC_END () flag to signify that the end of the stream is reached. + + A stream writing function should obviously be as quick as possible, because other streams (and MOD musics) can't be updated until it's finished. + It is better to return less data quickly, rather than spending a long time delivering the amount BASS requested. + Although a STREAMPROC may return less data than BASS requests, be careful not to do so by too much, too often. If the buffer level gets too low, BASS will automatically stall playback of the stream, until the whole buffer has refilled. + (BASS_DATA_AVAILABLE) can be used to check the buffer level, and can be used to check if playback has stalled. + A BASS_SYNC_STALL sync can also be set via , to be triggered upon playback stalling or resuming. + If you do return less than the requested amount of data, the number of bytes should still equate to a whole number of samples. + Some functions can cause problems if called from within a stream (or DSP) function. Do not call these functions from within a stream callback: + , , , or any other stream creation functions. + Also, do not call or with the same handle as received by the callback. + When streaming multi-channel sample data, the channel order of each sample is as follows: + 3 channels: left-front, right-front, center. + 4 channels: left-front, right-front, left-rear/side, right-rear/side. + 6 channels(5.1): left-front, right-front, center, LFE, left-rear/side, right-rear/side. + 8 channels(7.1): left-front, right-front, center, LFE, left-rear/side, right-rear/side, left-rear center, right-rear center. + + It is clever to NOT alloc buffer data (e.g. a float[]) everytime within the callback method, since ALL callbacks should be really fast! + And if you would do a 'float[] data = new float[]' every time here...the GarbageCollector would never really clean up that memory. + Sideeffects might occure, due to the fact, that BASS will call this callback too fast and too often... + However, this is not always the case, so in most examples it'll work just fine - but if you got problems - try moving any memory allocation things outside any callbacks. + + NOTE: When you pass an instance of a callback delegate to one of the BASS functions, this delegate object will not be reference counted. + This means .NET would not know, that it might still being used by BASS. The Garbage Collector might (re)move the delegate instance, if the variable holding the delegate is not declared as global. + So make sure to always keep your delegate instance in a variable which lives as long as BASS needs it, e.g. use a global variable or member. + + + A callback function to stream a file, in 44100hz 16-bit stereo: + + private STREAMPROC _myStreamCreate; // make it global, so that the GC can not remove it + private byte[] _data; // local data buffer + ... + _myStreamCreate = new STREAMPROC(MyFileProc); + FileStream _fs = File.OpenRead("test.raw"); + int channel = Bass.BASS_StreamCreate(44100, 2, BASSFlag.BASS_DEFAULT, _myStreamCreate, IntPtr.Zero); + Bass.BASS_ChannelPlay(channel, false); + ... + private int MyFileProc(int handle, IntPtr buffer, int length, IntPtr user) + { + // implementing the callback for BASS_StreamCreate... + // here we need to deliver PCM sample data + // increase the data buffer as needed + if (_data == null || _data.Length < length) + _data = new byte[length]; + int bytesread = _fs.Read( _data, 0, length ); + Marshal.Copy( _data, 0, buffer, bytesread ); + if ( bytesread < length ) + { + bytesread |= (int)BASSStreamProc.BASS_STREAMPROC_END; // set indicator flag + _fs.Close(); + } + return bytesread; + } + + + Private _myStreamCreate As STREAMPROC ' make it global, so that the GC can not remove it + Private _data As Byte() = Nothing ' our local buffer + ... + _myStreamCreate = New STREAMPROC(AddressOf MyFileProc) + Dim fs As FileStream = File.OpenRead("test.raw") + Dim channel As Integer = Bass.BASS_StreamCreate(44100, 2, BASSFlag.BASS_DEFAULT, _myStreamCreate, IntPtr.Zero) + Bass.BASS_ChannelPlay(channel, False) + ... + Private Function MyFileProc(ByVal handle As Integer, ByVal buffer As IntPtr, + ByVal length As Integer, ByVal user As IntPtr) As Integer + ' implementing the callback for BASS_StreamCreate... + ' here we need to deliver PCM sample data + ' increase the data buffer as needed + If _data = Nothing OrElse _data.Length < length Then + _data = New Byte(length) {} + End If + Dim bytesread As Integer = _fs.Read(_data, 0, length) + Marshal.Copy(_data, 0, buffer, bytesread) + If bytesread < length Then + bytesread = bytesread Or CInt(BASSStreamProc.BASS_STREAMPROC_END) ' set indicator flag + _fs.Close() + EndIf + Return bytesread + End Function + + If you're into C# you might also make use of native pointers in an unsafe code block: + + unsafe private int MyFileProcUnsafe(int handle, IntPtr buffer, int length, IntPtr user) + { + // simply cast the given IntPtr to a native pointer to byte values + byte *data = (byte*)buffer; + // read the file into the data pointer directly + int bytesread = length; + for (int a=0; a < length; a++) + { + int val = _fs.ReadByte(); + if (val != -1) + { + data[a] = (byte)val; // set the value + } + else + { + bytesread = a; + break; + } + } + // end of the file/stream? + if ( bytesread < length ) + { + bytesread |= (int)BASSStreamProc.BASS_STREAMPROC_END; // set indicator flag + _fs.Close(); + } + return bytesread; + } + + However, even if we directly access memory here, this is not really faster in that case, since we read the file byte per byte and also in a way perform a copy (we just use a single int buffer called val). + So in essence when you need to read from a file you should take care, that the file access and read operation is fast an additional Marshal.Copy wouldn't count much in terms of performance. + The only advantage we get here is actually, that we use less memory. + + + + + User file stream close callback function (to be used with ). + + The user instance data given when was called. + With a buffered file stream, this function is called as soon as reading reaches the end of the file. + If the stream is freed before then, this function could be called while its function is in progress. + If that happens, the function call should be immediately cancelled. + + See . + + + + User file stream length callback function (to be used with ). + + The user instance data given when was called. + The length of the file in bytes. + Returning 0 for a buffered file stream, makes BASS stream the file in blocks, and is equivalent to using the BASS_STREAM_BLOCK flag + in the call. + This function is called first thing, and is only used the once with buffered streams. + With unbuffered streams, it may be used again when testing for EOF (end of file), + allowing the file to grow in size. + + See . + + + + User file stream read callback function (to be used with ). + + Pointer to the buffer to put the data in. + Maximum number of bytes to read. + The user instance data given when was called. + The number of bytes read... -1 = end of file, 0 = end of file (buffered file stream only). + During creation of the stream, this function should try to return the amount of data requested. + After that, it can just return whatever is available up to the requested amount. + For an unbuffered file stream during playback, this function should be as quick as possible - + any delays will not only affect the decoding of the current stream, but also all other streams and MOD musics that are playing. + It is better to return less data (even none) rather than wait for more data. + A buffered file stream isn't affected by delays like this, as this function runs in its own thread then. + + See . + + + + User file stream seek callback function (to be used with ). + + Position in bytes to seek to. + The user instance data given when was called. + if successful, else . + See . + + + + User defined DSP callback function (to be used with ). + + The DSP handle (as returned by ). + Channel that the DSP is being applied to. + The pointer to the buffer to apply the DSP to. The sample data is in standard Windows PCM format - 8-bit samples are unsigned, 16-bit samples are signed, 32-bit floating-point samples range from -1 to 1 (not clipped, so can actually be outside this range). + The number of bytes to process. + The user instance data given when was called. + + A DSP function should obviously be as quick as possible... playing streams, MOD musics and other DSP functions can not be processed until it has finished. + Some functions can cause problems if called from within a DSP (or stream) function. Do not call these functions from within a DSP callback: + , , , (or any other stream creation functions). + Also, do not call with the same DSP handle as received by the callback, or , , with the same channel handle as received by the callback. + If the BASS_CONFIG_FLOATDSP config option is set, then DSP callback functions will always be passed 32-bit floating-point sample data, regardless of what the channels' actual sample format is. + + It is clever to NOT alloc buffer data (e.g. a float[]) everytime within the callback method, since ALL callbacks should be really fast! + And if you would do a 'float[] data = new float[]' every time here...the GarbageCollector would never really clean up that memory. + Sideeffects might occure, due to the fact, that BASS will call this callback too fast and too often... + However, this is not always the case, so in most examples it'll work just fine - but if you got problems - try moving any memory allocation things outside any callbacks. + + NOTE: When you pass an instance of a callback delegate to one of the BASS functions, this delegate object will not be reference counted. + This means .NET would not know, that it might still being used by BASS. The Garbage Collector might (re)move the delegate instance, if the variable holding the delegate is not declared as global. + So make sure to always keep your delegate instance in a variable which lives as long as BASS needs it, e.g. use a global variable or member. + + + You might use this code as a starting reference (it assumes 32-bit floating-point sample data): + + private DSPPROC _myDSPAddr; // make it global, so that the GC can not remove it + private float[] _data; // local data buffer + ... + _myDSPAddr = new DSPPROC(MyDSPCallback); + Bass.BASS_ChannelSetDSP(_stream, _myDSPAddr, IntPtr.Zero, 2); + ... + private void MyDSPCallback(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + if (length == 0 || buffer == IntPtr.Zero) + return; + // number of bytes in 32-bit floats, since length is in bytes + int l4 = length/4; + // increase the data buffer as needed + if (_data == null || _data.Length < l4) + _data = new float[l4]; + // copy from managed to unmanaged memory + Marshal.Copy(buffer, _data, 0, l4); + + // ... do your processing here + + // copy back from unmanaged to managed memory + Marshal.Copy(_data, 0, buffer, l4); + } + + + Private _myDSPAddr As DSPPROC ' make it global, so that the GC can not remove it + Private _data As Single() = Nothing ' our local buffer + ... + _myDSPAddr = New DSPPROC(AddressOf MyDSPCallback) + Bass.BASS_ChannelSetDSP(_stream, _myDSPAddr, IntPtr.Zero, 2) + ... + Private Sub MyGain(handle As Integer, channel As Integer, + buffer As IntPtr, length As Integer, user As IntPtr) + If length = 0 OrElse buffer = IntPtr.Zero Then + Return + End If + ' number of bytes in 32-bit floats, since length is in bytes + Dim l4 As Integer = length / 4 + ' increase the data buffer as needed + If _data Is Nothing OrElse _data.Length < l4 Then + _data = New Single(l4) {} + End If + ' copy from unmanaged to managed memory + Marshal.Copy(buffer, _data, 0, l4) + + // ... do your processing here + + ' copy back from unmanaged to managed memory + Marshal.Copy(_data, 0, buffer, l4) + End Sub + + If you're using C# you might even use unsafe code blocks to directly access memory via pointers, like in C/C++: + Note: such application must be compiled using the /unsafe compiler option! + + myDSPAddr = new DSPPROC(MyDSPGainUnsafe); + Bass.BASS_ChannelSetDSP(_stream, myDSPAddr, IntPtr.Zero, 2); + ... + // the unsafe callback + private DSPPROC myDSPAddr; // make it global, so that the Garbage Collector can not remove it + private void MyDSPGainUnsafe(int handle, int channel, IntPtr buffer, int length, IntPtr user) + { + if (_gainAmplification == 1f || length == 0 || buffer == IntPtr.Zero) + return; + // length is in bytes, so the number of floats to process is: + // length/4 : byte = 8-bit, float = 32-bit + int l4 = length/4; + unsafe + { + float *data = (float*)buffer; + for (int a=0; a<l4; a++) + { + data[a] *= _gainAmplification; + } + } + } + + Using unsafe code is fast and efficient (especially in DSP routines), but is not type safe (e.g. no overflow handling, no type checking etc.) - so you just need to know what you are doing. + + + + + Internet stream download callback function (to be used with ). + + The pointer to the buffer containing the downloaded data... = finished downloading. + The number of bytes in the buffer... 0 = HTTP or ICY tags. + The user instance data given when was called. + + The callback will be called before the call returns (if it's successful), with the initial downloaded data. So any initialization (eg. creating the file if writing to disk) needs to be done either before the call, or in the callback function. + When the BASS_STREAM_STATUS flag is specified in the call, HTTP and ICY tags may be passed to the callback during connection, before any stream data is received. The tags are given exactly as would be returned by . You can destinguish between HTTP and ICY tags by checking what the first string starts with ("HTTP" or "ICY"). + A download callback function could be used in conjunction with a BASS_SYNC_META sync set via , to save individual tracks to disk from a Shoutcast stream. + NOTE: When you pass an instance of a callback delegate to one of the BASS functions, this delegate object will not be reference counted. + This means .NET would not know, that it might still being used by BASS. The Garbage Collector might (re)move the delegate instance, if the variable holding the delegate is not declared as global. + So make sure to always keep your delegate instance in a variable which lives as long as BASS needs it, e.g. use a global variable or member. + + + Stream an MP3 file, and save a local copy: + + private FileStream _fs = null; + private DOWNLOADPROC _myDownloadProc; + private byte[] _data; // local data buffer + ... + _myDownloadProc = new DOWNLOADPROC(MyDownload); + int stream = Bass.BASS_StreamCreateURL("http://www.asite.com/afile.mp3", 0, + BASSFlag.BASS_DEFAULT, _myDownloadProc, IntPtr.Zero); + ... + private void MyDownload(IntPtr buffer, int length, IntPtr user) + { + if (_fs == null) + { + // create the file + _fs = File.OpenWrite( "output.mp3" ); + } + if (buffer == IntPtr.Zero) + { + // finished downloading + _fs.Flush(); + _fs.Close(); + } + else + { + // increase the data buffer as needed + if (_data == null || _data.Length < length) + _data = new byte[length]; + // copy from managed to unmanaged memory + Marshal.Copy(buffer, _data, 0, length); + // write to file + _fs.Write( _data, 0, length ); + } + } + + + Private _fs As FileStream = Nothing + Private _myDownloadProc As DOWNLOADPROC + Private _data() As Byte ' local data buffer + ... + _myDownloadProc = New DOWNLOADPROC(AddressOf MyDownload) + Dim stream As Integer = Bass.BASS_StreamCreateURL("http://www.asite.com/afile.mp3", 0, + BASSFlag.BASS_DEFAULT, _myDownloadProc, IntPtr.Zero) + ... + Private Sub MyDownload(buffer As IntPtr, length As Integer, user As IntPtr) + If _fs Is Nothing Then + ' create the file + _fs = File.OpenWrite("output.mp3") + End If + If buffer = IntPtr.Zero Then + ' finished downloading + _fs.Flush() + _fs.Close() + Else + ' increase the data buffer as needed + If _data Is Nothing OrElse _data.Length < length Then + _data = New Byte(length) {} + End If + ' copy from managed to unmanaged memory + Marshal.Copy(buffer, _data, 0, length) + ' write to file + _fs.Write(_data, 0, length) + End If + End Sub + + Note: If you are into C# the above example can also make use of usafe code blocks using native pointers to read the data from BASS and to write it to a file: + + // within your download callback method... + // assuming you have created a: BinaryWriter bw = new BinaryWriter(_fs); + unsafe + { + // simply cast the given IntPtr to a native pointer to short values + // assuming you receive 16-bit sample data here + short *data = (short*)buffer; + for (int a = 0; a < length/2; a++) + { + // write the received sample data to a local file + bw.Write( data[a] ); + } + } + + + + + + User defined synchronizer callback function (see for details). + + The sync handle that has occured (as returned by ). + The channel that the sync occured on. + Additional data associated with the sync's occurance. + The user instance data given when was called. + + BASS creates a single thread dedicated to executing sync callback functions, so a callback function should be quick as other syncs cannot be processed until it has finished. Attribute slides () are also performed by the sync thread, so are also affected if a sync callback takes a long time. + "Mixtime" syncs (BASS_SYNC_MIXTIME) are not executed in the sync thread, but immediately in whichever thread triggers them. In most cases that will be an update thread, and so the same restrictions that apply to stream callbacks () also apply here. + can be used in a mixtime sync to implement custom looping, eg. set a BASS_SYNC_POS sync at the loop end position and seek to the loop start position in the callback. + NOTE: When you pass an instance of a callback delegate to one of the BASS functions, this delegate object will not be reference counted. + This means .NET would not know, that it might still being used by BASS. The Garbage Collector might (re)move the delegate instance, if the variable holding the delegate is not declared as global. + So make sure to always keep your delegate instance in a variable which lives as long as BASS needs it, e.g. use a global variable or member. + + + Do some processing until a MOD music reaches the 10th order + + private volatile bool _order10 = false; // the order 10 flag + private SYNCPROC _mySyncProc; + ... + // set the one-time order 10 sync + _mySyncProc = new SYNCPROC(MySync); + Bass.BASS_ChannelSetSync(music, BASSSync.BASS_SYNC_MUSICPOS | BASSSync.BASS_SYNC_ONETIME, + Utils.MakeLong64(10,0), _mySyncProc, IntPtr.Zero); + while (!_order10) + { + // order 10 has not arrived, so do some processing + Thread.Sleep(0); + } + // order 10 has arrived! + ... + // the sync callback + private void MySync(int syncHandle, int channel, int data, IntPtr user) + { + _order10 = true; // set the order 10 flag + } + + + Private _order10 As Boolean = False ' the order 10 flag + Private _mySyncProc As SYNCPROC + ... + ' set the one-time order 10 sync + _mySyncProc = New SYNCPROC(AddressOf MySync) + Bass.BASS_ChannelSetSync(music, BASSSync.BASS_SYNC_MUSICPOS Or BASSSync.BASS_SYNC_ONETIME, + Utils.MakeLong64(10, 0), _mySyncProc, IntPtr.Zero) + While Not _order10 + ' order 10 has not arrived, so do some processing + Thread.Sleep(0) + End While + ' order 10 has arrived! + ... + ' the sync callback + Private Sub MySync(syncHandle As Integer, channel As Integer, data As Integer, user As IntPtr) + _order10 = True ' set the order 10 flag + End Sub + + Process metadata received from an internet stream: + + private SYNCPROC _mySync; + ... + int stream = Bass.BASS_StreamCreateURL(url, 0, BASSFlag.BASS_DEFAULT, null, 0); + // set a sync to get notified on stream title updates + _mySync = new SYNCPROC(MetaSync); + Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_META, 0, _mySync, IntPtr.Zero); + Bass.BASS_ChannelPlay(stream, false); + ... + private void MetaSync(int handle, int channel, int data, IntPtr user) + { + // BASS_SYNC_META is triggered + string[] tags = Bass.BASS_ChannelGetTagsMETA(channel); + foreach (string tag in tags) + Console.WriteLine(tag); + } + + + Private _mySync As SYNCPROC + ... + Dim stream As Integer = Bass.BASS_StreamCreateURL(url, 0, BASSFlag.BASS_DEFAULT, Nothing, 0) + ' set a sync to get notified on stream title updates + _mySync = New SYNCPROC(AddressOf MetaSync) + Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_META, 0, _mySync, IntPtr.Zero) + Bass.BASS_ChannelPlay(stream, False) + ... + Private Sub MetaSync(ByVal handle As Integer, ByVal channel As Integer, + ByVal data As Integer, ByVal user As IntPtr) + ' BASS_SYNC_META is triggered + Dim tags() As String = Bass.BASS_ChannelGetTagsMETA(channel) + Dim tag As String + For Each tag In tags + Console.WriteLine(tag) + End Sub + + Perform a loop between a start and end position: + + private int _loopSync = 0; + private SYNCPROC _loopSyncCallback; + ... + long loopStartPos = 1024; // set to whatever you need + long loopEndPos = 20480; // set to whatever you need + _loopSyncCallback = new SYNCPROC(LoopSync); + _loopSync = Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_POS | BASSSync.BASS_SYNC_MIXTIME, + loopEndPos, _loopSyncCallback, new IntPtr(loopStartPos)); + ... + // to remove the loop call this + Bass.Bass.BASS_ChannelRemoveSync(stream, _loopSync); + ... + // the sync callback + private void LoopSync(int syncHandle, int channel, int data, IntPtr user) + { + // move the position to the start (which is given in the user data) + Bass.BASS_ChannelSetPosition(channel, user.ToInt64()); + } + + + Private _loopSync As Integer = 0 + Private _loopSyncCallback As SYNCPROC + ... + Dim loopStartPos As Long = 1024 ' set to whatever you need + Dim loopEndPos As Long = 20480 ' set to whatever you need + _loopSyncCallback = New SYNCPROC(AddressOf LoopSync); + _loopSync = Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_POS Or BASSSync.BASS_SYNC_MIXTIME, + loopEndPos, _loopSyncCallback, New IntPtr(loopStartPos)) + ... + ' to remove the loop call this + Bass.Bass.BASS_ChannelRemoveSync(stream, _loopSync) + ... + ' the sync callback + Private Sub LoopSync(ByVal handle As Integer, ByVal channel As Integer, + ByVal data As Integer, ByVal user As IntPtr) + ' move the position to the start (which is given in the user data) + Bass.BASS_ChannelSetPosition(channel, user.ToInt64()) + End Sub + + + + + + User defined callback function to process recorded sample data. + + The recording handle that the data is from. + The pointer to the buffer containing the recorded sample data. The sample data is in standard Windows PCM format, that is 8-bit samples are unsigned, 16-bit samples are signed, 32-bit floating-point samples range from -1 to +1. + The number of bytes in the buffer. + The user instance data given when was called. + Return to stop recording, and anything else to continue recording. + + should not be used to free the recording device within a recording callback function. Nor should be used to stop the recording; return to do that instead. + + It is clever to NOT alloc any buffer data (e.g. a byte[]) everytime within the callback method, since ALL callbacks should be really fast! + And if you would do a 'byte[] data = new byte[]' every time here...the GarbageCollector would never really clean up that memory. + Sideeffects might occure, due to the fact, that BASS will call this callback too fast and too often... + + NOTE: When you pass an instance of a callback delegate to one of the BASS functions, this delegate object will not be reference counted. + This means .NET would not know, that it might still being used by BASS. The Garbage Collector might (re)move the delegate instance, if the variable holding the delegate is not declared as global. + So make sure to always keep your delegate instance in a variable which lives as long as BASS needs it, e.g. use a global variable or member. + + + + private RECORDPROC _myRecProc; // make it global, so that the GC can not remove it + private int _byteswritten = 0; + private byte[] _recbuffer; // local recording buffer + ... + if ( Bass.BASS_RecordInit(-1) ) + { + _myRecProc = new RECORDPROC(MyRecording); + int recHandle = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, _myRecProc, IntPtr.Zero); + ... + // start recording + Bass.BASS_ChannelPlay(recHandle, false); + } + ... + private bool MyRecording(int handle, IntPtr buffer, int length, IntPtr user) + { + bool cont = true; + if (length > 0 && buffer != IntPtr.Zero) + { + // increase the rec buffer as needed + if (_recbuffer == null || _recbuffer.Length < length) + _recbuffer = new byte[length]; + // copy from managed to unmanaged memory + Marshal.Copy(buffer, _recbuffer, 0, length); + _byteswritten += length; + // write to file + ... + // stop recording after a certain amout (just to demo) + if (_byteswritten > 800000) + cont = false; // stop recording + } + return cont; + } + + + Private _myRecProc As RECORDPROC ' make it global, so that the GC can not remove it + Private _byteswritten As Integer = 0 + Private _recbuffer() As Byte ' local recording buffer + ... + If Bass.BASS_RecordInit(-1) Then + _myRecProc = New RECORDPROC(AddressOf MyRecording) + Dim recHandle As Integer = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, _myRecProc, IntPtr.Zero) + ... + ' start recording + Bass.BASS_ChannelPlay(recHandle, False) + End If + ... + Private Function MyRecording(handle As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Boolean + Dim cont As Boolean = True + If length > 0 AndAlso buffer <> IntPtr.Zero Then + ' increase the rec buffer as needed + If _recbuffer Is Nothing OrElse _recbuffer.Length < length Then + _recbuffer = New Byte(length) {} + End If + ' copy from managed to unmanaged memory + Marshal.Copy(buffer, _recbuffer, 0, length) + _byteswritten += length + ' write to file + ... + ' stop recording after a certain amout (just to demo) + If _byteswritten > 800000 Then + cont = False ' stop recording + End If + End If + Return cont + End Function + + If you are into C# you might also use an unsafe codeblock with native pointer access + (which might be must faster than the above - depending on what you are doing with the data): + + private unsafe bool MyRecording(int handle, IntPtr buffer, int length, IntPtr user) + { + bool cont = true; + if (length > 0 && buffer != IntPtr.Zero) + { + // assuming 16-bit sample data here + short *data = (short*)buffer; + ... + + // stop recording after a certain amout (just to demo) + if (_byteswritten > 800000) + cont = false; // stop recording + } + return cont; + } + + + + + + BASS.NET API wrapper for BASS_WINAMP.DLL + Requires: bass_winamp.dll - Winamp Input plugins support Add-On - available @ www.un4seen.com. + + + BassWinamp is an extention to the BASS audio library, providing a set of functions for adding Winamp Input plugins support. This adds more format support for the Bass library. + Currently the new BASS plugin system is not supported. So you need to call the method here directly. + + + + + NOT used - all members are static! + + + + + Returns weather the Winamp input plugin supports seeking? + + The handle of the winamp input plugin. + if the input plugin support seeking, else is returned. + + + + Returns weather the Winamp input plugin make use of the winamp output? + + The handle of the winamp input plugin. + if the input plugin uses output, else is returned. + + + + + + + + + + + + + Returns information about a given file. + + The name of the file to retrieve the information from. + Returns the title of the given file. + Returns the length of the given file in milliseconds. + if the information was retrieved successfully, else is returned. + + + int len = 0; + string title = String.Empty; + if ( BassWinamp.BASS_WINAMP_GetFileInfo("testfile.mp3", ref title, ref len) ) + { + Console.WriteLine( "Title={0}, Length={1}ms", title, len ); + } + + + + + + Shows the Winamp input plugin information dialog for a given file (like pressing Alt+3 in Winamp). + + The name of the file to retrieve the information from. + The application's main window... IntPtr.Zero = the current foreground window (use this for console applications, or pass this.Handle). + if the info dialog was called successfully, else is returned. + + Show the winamp info dialog related to a file: + + int pluginHandle = BassWinamp.BASS_WINAMP_LoadPlugin( @"C:\Programme\Winamp\Plugins\in_mp3.dll" ); + if (pluginHandle != 0) + { + BassWinamp.BASS_WINAMP_InfoDlg( "test.mp3", this.Handle ); + } + + + + + + Internal only. + + + + + + + Gets the name of the winamp input plugin. + + The handle of the winamp input plugin. + The name of the plugin, or if the call failed. + + Get the name of the winamp input plugin: + + int pluginHandle = BassWinamp.BASS_WINAMP_LoadPlugin( @"C:\Programme\Winamp\Plugins\in_mp3.dll" ); + if (pluginHandle != 0) + { + Console.WriteLine( BassWinamp.BASS_WINAMP_GetName(pluginHandle) ); + } + + + + + + Gets the supported file filter extensions of the given winamp input plug-in. + + The handle of the winamp input plugin. + Returns a pointer to a list of null-terminated strings (ending with a double null) representing the supported extensions of the winamp input plugin. + Use to convert this to an array of string. + Or use instead. + + + Example of how extentions are returned: + "Layer 3 MPEG\0*.mp3;*.mp2\0Layer 2 MPEG\0*.mp2\0Layer 1 MPEG\0*.mpg\0\0" + + + + + Gets the supported file filter extensions of the given winamp input plug-in. + + The handle of the winamp input plugin. + Returns a file filter string in the format: + "Layer 3 MPEG|*.mp3;*.mp2|Layer 2 MPEG|*.mp2|Layer 1 MPEG|*.mpg". + Returns NULL, if an error occurred. + + Uses internally. + + + int pluginHandle = BassWinamp.BASS_WINAMP_LoadPlugin( @"C:\Programme\Winamp\Plugins\in_mp3.dll" ); + if (pluginHandle != 0) + { + Console.WriteLine( BassWinamp.BASS_WINAMP_GetExtentionsFilter(pluginHandle) ); + } + + + + + + + + + + + + + + Gets a list of all winamp input plug-ins in a given directory. + If the BASS_WINAMP_FIND_COMMALIST flag was set it will automatically be removed. + + The path of the directory to search in. + Any combination of the following (see ): + + BASS_WINAMP_FIND_INPUTFind input plug-ins. Should and must always be specified. + BASS_WINAMP_FIND_RECURSIVERecursively loop through all sub-directories as well. + + + A string array of the plug-in list or if no plug-in could be found. + + + string[] waPlugIns = BassWinamp.BASS_WINAMP_FindPlugins( @"C:\Programme\Winamp\Plugins", BASSWINAMPFindPlugin.BASS_WINAMP_FIND_INPUT | BASSWINAMPFindPlugin.BASS_WINAMP_FIND_RECURSIVE ); + foreach (string waPlugIn in waPlugIns) + { + Console.WriteLine( waPlugIn ); + } + + + + + + Loads a Winamp input plug-in. + + The file name of the plug-in to load. + The handle of the loaded winamp input plug-in or 0 if it failed. + + + int pluginHandle = BassWinamp.BASS_WINAMP_LoadPlugin( @"C:\Programme\Winamp\Plugins\in_mp3.dll" ); + + Typically you will use one of the returned strings of . + + + + + Unloads a Winamp input plug-in which had been loaded via before. + + The handle of the winamp input plugin. + + + + Gets the version of a loaded Winamp input plug-in. + + The handle of the winamp input plugin. + The version number. Use resp. to get the major resp. minor version number. + + + + Shows the configuration dialog of the loaded Winamp input plug-in. + + The handle of the winamp input plugin. + The application's main window... IntPtr.Zero = the current foreground window (use this for console applications, or pass this.Handle). + + + int pluginHandle = BassWinamp.BASS_WINAMP_LoadPlugin( @"C:\Programme\Winamp\Plugins\in_mp3.dll" ); + if (pluginHandle != 0) + { + BassWinamp.BASS_WINAMP_ConfigPlugin( pluginHandle, this.Handle ); + } + + + + + + Shows the about dialog of the loaded Winamp input plug-in. + + The handle of the winamp input plugin. + The application's main window... IntPtr.Zero = the current foreground window (use this for console applications, or pass this.Handle). + + + int pluginHandle = BassWinamp.BASS_WINAMP_LoadPlugin( @"C:\Programme\Winamp\Plugins\in_mp3.dll" ); + if (pluginHandle != 0) + { + BassWinamp.BASS_WINAMP_AboutPlugin( pluginHandle, this.Handle ); + } + + + + + + The WINAMP Add-On ONLY SUPPORTS ANSI FILENAMES! + + + + + + + + Creates a stream from a Winamp input plug-in. + + Filename for which a stream should be created. + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + Load the winamp mp3 input plugin and play a file: + + int pluginHandle = BassWinamp.BASS_WINAMP_LoadPlugin( @"C:\Programme\Winamp\Plugins\in_mp3.dll" ); + if (pluginHandle != 0) + { + int waStream = BassWinamp.BASS_WINAMP_StreamCreate( "test.mp3", BASSFlag.BASS_SAMPLE_SOFTWARE | BASSFlag.BASS_STREAM_AUTOFREE ); + if (waStream != 0) + { + Bass.BASS_ChannelPlay( waStream, false ); + } + } + + + + + + Loads this library into memory. The library will be search in the current application directory. + + TRUE, if the module could be loaded successfully, else FALSE. + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + TRUE, if the module could be loaded successfully, else FALSE. + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Unloads this library. This must be called when you have previously called . + + TRUE, if the module has been unloaded successfully, else FALSE. + For more information see . + + + + Flags to be used with . + + + + + Find input plug-ins. Should and must always be specified. + + + + + Recursively loop through all sub-directories as well. + + + + + Return the result as a comma seperated list in the format: item1,item2,"item with , commas",item4,"item with space" + If not specified a list of null-terminated Ansi strings will be returned ending with a double-null. + + + + + BASS.NET API wrapper for BASS_APE.DLL + Requires: bass_ape.dll - Monkey's Audio Codec (APE) Add-On - available @ www.un4seen.com. + + + BASS_APE is an extension to the BASS audio library, enabling the playback of Monkey's Audio files. + Monkey's Audio is a fast and powerful way to compress digital music. Unlike traditional methods, such as MP3, Vorbis or WMA which permanently discard quality to save space, Monkey's Audio makes perfect, lossless copies of your music, while still being able to save a lot of space. + The Monkey's Audio format is used in the same way as any of the built-in BASS stream formats. Simply call to load the add-on into BASS and benefit the usage of the standard sample/stream/URL/user functions, or call the /URL/User functions. + More information can be found on www.monkeysaudio.com. + + + + + NOT used - all members are static! + + + + + + + + + + + + + + + + Creates a sample stream from a Monkey's Audio file. + This overload implements UNICODE filenames. The BASS_UNICODE flag will be added automatically, since all .Net strings are always unicode. + + Filename for which a stream should be created. + File offset to begin streaming from. + Data length... 0 = use all data up to the end of the file. + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + + + + + + + + + + + + Creates a sample stream from a Monkey's Audio memory IntPtr. + This overload implements streaming from memory. + + An unmanaged pointer to the memory location as an IntPtr. + Offset to begin streaming from (unused for memory streams, set to 0). + Data length (needs to be set to the length of the memory streams in bytes which should be played). + Any combination of these flags: see . + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + + + + Creates a sample stream from a Monkey's Audio file via a user callback function. + + File system to use: see . + Any combination of these flags: see . + The user defined file functions (see ). + User instance data to pass to the callback functions. + If successful, the new stream's handle is returned, else 0 is returned. Use to get the error code. + Works in the same way does - so for details look there. + See . + + + + Supported file extensions of the bass_ape.dll + + + + + Supported file format name of the bass_ape.dll + + + + + Loads this library into memory. The library will be search in the current application directory. + + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + The disadvantage of this method is, that the standard plugin support for is not working - so you would need to use the native add-on methods! + + + + + Loads this library into memory. The library will be loaded from the given path. + + The path of the directory in which to search. + , if the module could be loaded successfully, else . + This method can be used to make sure, that this specific library has been loaded. + Normally an external library will be loaded into memory when either of the declared methods will be called for the very first time. + This results in the very first call to a library method being slower than all subsequent calls. + Moreover some of the BASS libraries and add-ons will introduce new options to the main BASS lib, e.g. new parameters which can be used with or . + But in order to enable BASS using these new options the respective library must have been already loaded. This method can be used to ensure this. + This method can also be used as an alternative way to load a library instead of using the BASS way via . + The advantage of this is method here is, that you might locate all your bass dll's in a different directory. + + + + + Unloads this library. This must be called when you have previously called . + + , if the module has been unloaded successfully, else . + For more information see . + + + diff --git a/DoubanFM.Bass/BassEngine.cs b/DoubanFM.Bass/BassEngine.cs new file mode 100644 index 0000000..aefafc1 --- /dev/null +++ b/DoubanFM.Bass/BassEngine.cs @@ -0,0 +1,1102 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Linq; +using System.Reflection; +using System.Text; +using System.IO; +using System.Windows.Threading; +using System.ComponentModel; +using System.Diagnostics; +using System.Windows; +using System.Windows.Interop; +using System.Threading; +using System.Runtime.InteropServices; + +namespace DoubanFM.Bass +{ + + /// + /// Bass播放器 + /// + public class BassEngine : WPFSoundVisualizationLib.ISpectrumPlayer, INotifyPropertyChanged, IDisposable + { + #region Fields + /// + /// BassEngine的唯一实例 + /// + private static BassEngine instance; + /// + /// 用于更新播放进度的计时器 + /// + private readonly DispatcherTimer positionTimer = new DispatcherTimer(DispatcherPriority.ApplicationIdle); + private readonly int maxFFT = (int)Enum.Parse(typeof(Un4seen.Bass.BASSData), ConfigurationManager.AppSettings["Bass.MaxFFT"]); + private readonly int getFFTFrequencyIndexLength = int.Parse(ConfigurationManager.AppSettings["Bass.GetFFTFrequencyIndexLength"]); + /// + /// 当播放结束时调用 + /// + private readonly Un4seen.Bass.SYNCPROC endTrackSyncProc; + + private int sampleFrequency = int.Parse(ConfigurationManager.AppSettings["Bass.SampleFrequency"]); + /// + /// 当前流的句柄 + /// + private int activeStreamHandle; + /// + /// 可以使用播放命令 + /// + private bool canPlay; + /// + /// 可以使用暂停命令 + /// + private bool canPause; + /// + /// 是否正在播放 + /// + private bool isPlaying; + /// + /// 可以使用停止命令 + /// + private bool canStop; + /// + /// 音频长度 + /// + private TimeSpan channelLength = TimeSpan.Zero; + /// + /// 当前播放进度 + /// + private TimeSpan currentChannelPosition = TimeSpan.Zero; + private bool inChannelSet; + private bool inChannelTimerUpdate; + /// + /// 用于异步打开网络音频文件的线程 + /// + private Thread onlineFileWorker; + /// + /// 待执行的命令 + /// + enum PendingOperation + { + /// + /// 无 + /// + None = 0, + /// + /// 播放 + /// + Play, + /// + /// 暂停 + /// + Pause + }; + /// + /// 待执行的命令,当打开网络上的音频时非常有用 + /// + private PendingOperation pendingOperation = PendingOperation.None; + /// + /// 音量 + /// + private double volume; + /// + /// 是否静音 + /// + private bool isMuted; + /// + /// 保存正在打开的文件的地址,当短时间内多次打开网络文件时,这个字段保存最后一次打开的文件,可以使其他打开文件的操作失效 + /// + private string openningFile = null; + + private readonly Un4seen.Bass.BASSInit initFlags = (Un4seen.Bass.BASSInit) Enum.Parse(typeof (Un4seen.Bass.BASSInit), ConfigurationManager.AppSettings["Bass.InitFlags"]); + + private static readonly Dictionary stringHandles = new Dictionary(); + private Un4seen.Bass.BASSFlag openUrlConfig = (Un4seen.Bass.BASSFlag)Enum.Parse(typeof(Un4seen.Bass.BASSFlag), ConfigurationManager.AppSettings["Bass.OpenUrlConfig"]); + private static readonly List pluginHandles; + #endregion + + #region Constructor + static BassEngine() + { + //注册Bass.Net,不注册就会弹出一个启动画面 + Un4seen.Bass.BassNet.Registration("yk000123@sina.com", "2X34201017282922"); + + //判断当前系统是32位系统还是64位系统,并加载对应版本的bass.dll + string exeFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().GetModules()[0].FullyQualifiedName); + string libraryPathSetting = Un4seen.Bass.Utils.Is64Bit ? "Bass.LibraryPathX64" : "Bass.LibraryPathX86"; + string bassDllBasePath = Path.Combine(exeFolder, ConfigurationManager.AppSettings[libraryPathSetting]); + + // now load all libs manually + Un4seen.Bass.Bass.LoadMe(bassDllBasePath); + var loadedPlugins = + Un4seen.Bass.Bass.BASS_PluginLoadDirectory( + string.Format(ConfigurationManager.AppSettings["Bass.PluginPathFormat"], bassDllBasePath)); + if (loadedPlugins != null) + { + foreach (var item in loadedPlugins) + { + Debug.WriteLine(string.Format("Plugin loaded: {0}", item.Value)); + } + pluginHandles = loadedPlugins.Keys.ToList(); + } + else + { + pluginHandles = new List(); + } + + //BassMix.LoadMe(targetPath); + //... + //loadedPlugIns = Bass.BASS_PluginLoadDirectory(targetPath); + //... + + SetConfigs(ConfigurationManager.AppSettings["Bass.SetConfigOnInitialization"]); + } + + private BassEngine(DeviceInfo? deviceInfo = null) + { + Initialize(deviceInfo); + //设置播放结束的回调 + endTrackSyncProc = EndTrack; + } + #endregion + + #region Destructor + ~BassEngine() + { + Dispose(false); + } + #endregion + + #region IDisposable + bool _disposed; + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + if (onlineFileWorker != null) + { + onlineFileWorker.Abort(); + onlineFileWorker = null; + } + } + // at the end of your application call this! + foreach (var handle in pluginHandles) + { + Un4seen.Bass.Bass.BASS_PluginFree(handle); + } + Un4seen.Bass.Bass.BASS_Free(); + Un4seen.Bass.Bass.FreeMe(); + //BassMix.FreeMe(targetPath); + //... + //foreach (int plugin in LoadedBassPlugIns.Keys) + // Bass.BASS_PluginFree(plugin); + + foreach (var handle in stringHandles.Values) + { + if (handle != IntPtr.Zero) + Marshal.FreeHGlobal(handle); + } + stringHandles.Clear(); + + _disposed = true; + } + } + #endregion + + #region INotifyPropertyChanged + public event PropertyChangedEventHandler PropertyChanged; + + private void NotifyPropertyChanged(String info) + { + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs(info)); + } + } + #endregion + + #region Singleton Instance + /// + /// 获取BassEngine的唯一实例 + /// + public static BassEngine Instance + { + get + { + if (instance == null) + instance = new BassEngine(); + return instance; + } + } + /// + /// 显式初始化 + /// + public static void ExplicitInitialize(DeviceInfo? deviceInfo = null) + { + if (instance == null) + instance = new BassEngine(deviceInfo); + } + #endregion + + #region Public Methods + + /// + /// 获取设备列表 + /// + /// + public static DeviceInfo[] GetDeviceInfos() + { + List results = new List(); + var devices = Un4seen.Bass.Bass.BASS_GetDeviceInfos().ToList(); + foreach (var device in devices) + { + if (device.IsEnabled && !string.Equals(device.name, "No sound", StringComparison.CurrentCultureIgnoreCase) && !string.Equals(device.name, "Default", StringComparison.CurrentCultureIgnoreCase)) + { + results.Add(new DeviceInfo { ID = device.id, Name = device.name, Driver = device.driver }); + } + } + return results.ToArray(); + } + /// + /// 更换设备 + /// + public void ChangeDevice(DeviceInfo? device) + { + int deviceNO = FindDevice(device); + int oldDeviceNO = Un4seen.Bass.Bass.BASS_GetDevice(); + if (oldDeviceNO != deviceNO) + { + if (!Un4seen.Bass.Bass.BASS_GetDeviceInfo(deviceNO).IsInitialized) + { + IntPtr handle = IntPtr.Zero; + if (Application.Current.MainWindow != null) + { + handle = new WindowInteropHelper(Application.Current.MainWindow).EnsureHandle(); + } + if (!Un4seen.Bass.Bass.BASS_Init(deviceNO, sampleFrequency, initFlags, handle)) + { + throw new Exception(Un4seen.Bass.Bass.BASS_ErrorGetCode().ToString()); + } + } + if (activeStreamHandle != 0) + { + if (!Un4seen.Bass.Bass.BASS_ChannelSetDevice(activeStreamHandle, deviceNO)) + { + throw new Exception(Un4seen.Bass.Bass.BASS_ErrorGetCode().ToString()); + } + } + if (!Un4seen.Bass.Bass.BASS_SetDevice(oldDeviceNO)) + { + throw new Exception(Un4seen.Bass.Bass.BASS_ErrorGetCode().ToString()); + } + if (!Un4seen.Bass.Bass.BASS_Free()) + { + throw new Exception(Un4seen.Bass.Bass.BASS_ErrorGetCode().ToString()); + } + if (!Un4seen.Bass.Bass.BASS_SetDevice(deviceNO)) + { + throw new Exception(Un4seen.Bass.Bass.BASS_ErrorGetCode().ToString()); + } + + } + Device = device; + } + + /// + /// 停止当前音频,并释放资源 + /// + public void Stop() + { + //Debug.WriteLine("已调用BassEngine.Stop()"); + + if (canStop) + { + ChannelPosition = TimeSpan.Zero; + if (ActiveStreamHandle != 0) + { + Un4seen.Bass.Bass.BASS_ChannelStop(ActiveStreamHandle); + Un4seen.Bass.Bass.BASS_ChannelSetPosition(ActiveStreamHandle, ChannelPosition.TotalSeconds); + //Debug.WriteLine("已调用BASS_ChannelStop()"); + } + IsPlaying = false; + CanStop = false; + CanPlay = false; + CanPause = false; + } + + FreeCurrentStream(); + pendingOperation = PendingOperation.None; + } + + /// + /// 暂停当前音频 + /// + public void Pause() + { + //Debug.WriteLine("已调用BassEngine.Pause()"); + if (IsPlaying && CanPause) + { + Un4seen.Bass.Bass.BASS_ChannelPause(ActiveStreamHandle); + IsPlaying = false; + CanPlay = true; + CanPause = false; + pendingOperation = PendingOperation.None; + } + else + { + pendingOperation = PendingOperation.Pause; + } + } + + /// + /// 播放当前音频 + /// + public void Play() + { + //Debug.WriteLine("已调用BassEngine.Play()"); + if (CanPlay) + { + PlayCurrentStream(); + IsPlaying = true; + CanPause = true; + CanPlay = false; + CanStop = true; + pendingOperation = PendingOperation.None; + } + else + { + pendingOperation = PendingOperation.Play; + } + } + + /// + /// 打开文件 + /// + /// 文件名 + public void OpenFile(string filename) + { + openningFile = filename; + //Debug.WriteLine("已调用BassEngine.OpenFile()"); + Stop(); + pendingOperation = PendingOperation.None; + + var flag = (Un4seen.Bass.BASSFlag) Enum.Parse(typeof (Un4seen.Bass.BASSFlag), ConfigurationManager.AppSettings["Bass.OpenFileConfig"]); + int handle = Un4seen.Bass.Bass.BASS_StreamCreateFile(filename, 0, 0, flag); + + if (handle != 0) + { + ActiveStreamHandle = handle; + ChannelLength = TimeSpan.FromSeconds(Un4seen.Bass.Bass.BASS_ChannelBytes2Seconds(ActiveStreamHandle, Un4seen.Bass.Bass.BASS_ChannelGetLength(ActiveStreamHandle, 0))); + Un4seen.Bass.BASS_CHANNELINFO info = new Un4seen.Bass.BASS_CHANNELINFO(); + Un4seen.Bass.Bass.BASS_ChannelGetInfo(ActiveStreamHandle, info); + sampleFrequency = info.freq; + + int syncHandle = Un4seen.Bass.Bass.BASS_ChannelSetSync(ActiveStreamHandle, + Un4seen.Bass.BASSSync.BASS_SYNC_END, + 0, + endTrackSyncProc, + IntPtr.Zero); + + if (syncHandle == 0) + throw new ArgumentException("Error establishing End Sync on file stream.", "filename"); + + CanPlay = true; + RaiseOpenSucceededEvent(); + + switch (pendingOperation) + { + case PendingOperation.None: + break; + case PendingOperation.Play: + Play(); + break; + case PendingOperation.Pause: + Pause(); + break; + default: + break; + } + } + else + { + RaiseOpenFailedEvent(); + } + } + + /// + /// 打开网络地址 + /// + /// URL地址 + public void OpenUrlAsync(string url) + { + openningFile = url; + //Debug.WriteLine("已调用BassEngine.OpenUrlAsync()"); + + Stop(); + pendingOperation = PendingOperation.None; + + onlineFileWorker = new Thread(new ThreadStart(() => + { + int handle = Un4seen.Bass.Bass.BASS_StreamCreateURL(url, 0, openUrlConfig, null, IntPtr.Zero); + + Application.Current.Dispatcher.BeginInvoke(new Action(() => + { + if (handle != 0) + { + if (openningFile == url) //该文件为正在打开的文件 + { + ActiveStreamHandle = handle; + ChannelLength = TimeSpan.FromSeconds(Un4seen.Bass.Bass.BASS_ChannelBytes2Seconds(ActiveStreamHandle, Un4seen.Bass.Bass.BASS_ChannelGetLength(ActiveStreamHandle, 0))); + Un4seen.Bass.BASS_CHANNELINFO info = new Un4seen.Bass.BASS_CHANNELINFO(); + Un4seen.Bass.Bass.BASS_ChannelGetInfo(ActiveStreamHandle, info); + sampleFrequency = info.freq; + + int syncHandle = Un4seen.Bass.Bass.BASS_ChannelSetSync(ActiveStreamHandle, + Un4seen.Bass.BASSSync.BASS_SYNC_END, + 0, + endTrackSyncProc, + IntPtr.Zero); + + if (syncHandle == 0) + throw new ArgumentException("Error establishing End Sync on file stream.", "url"); + + CanPlay = true; + RaiseOpenSucceededEvent(); + + switch (pendingOperation) + { + case PendingOperation.None: + break; + case PendingOperation.Play: + Play(); + break; + case PendingOperation.Pause: + Pause(); + break; + default: + break; + } + } + else //该文件不是正在打开的文件(即文件已过时,可能的原因是UI线程较忙,调用onlineFileWorker.Abort()时BeginInvoke的内容已提交,但还未执行) + { + if (!Un4seen.Bass.Bass.BASS_StreamFree(handle)) + { + Debug.WriteLine("BASS_StreamFree失败:" + Un4seen.Bass.Bass.BASS_ErrorGetCode()); + } + //Debug.WriteLine("已调用BASS_StreamFree()"); + } + } + else + { + Debug.WriteLine(Un4seen.Bass.Bass.BASS_ErrorGetCode()); + RaiseOpenFailedEvent(); + } + })); + onlineFileWorker = null; + })); + onlineFileWorker.IsBackground = true; + onlineFileWorker.Start(); + } + + /// + /// 设置代理服务器 + /// + /// 主机 + /// 端口 + /// 用户名 + /// 密码 + public void SetProxy(string host, int port, string username = null, string password = null) + { + //格式:user:pass@server:port + StringBuilder sb = new StringBuilder(); + + //有用户名和密码的情形 + if (!string.IsNullOrEmpty(username)) + { + if (string.IsNullOrEmpty(password)) + throw new ArgumentException("密码为空", "password"); + sb.Append(username); + sb.Append(":"); + sb.Append(password); + } + + if (string.IsNullOrEmpty(host)) + throw new ArgumentException("主机为空", "host"); + sb.Append("@"); + + //添加主机和端口号 + if (host.Contains(':')) + throw new ArgumentException("主机不能包含符号:", "host"); + sb.Append("http://"); + sb.Append(host); + sb.Append(":"); + sb.Append(port); + + string proxyString = sb.ToString(); + + if (!SetConfig(Un4seen.Bass.BASSConfig.BASS_CONFIG_NET_PROXY, proxyString)) + { + throw new Exception("设置代理失败:" + Un4seen.Bass.Bass.BASS_ErrorGetCode()); + } + } + + /// + /// 使用默认代理服务器 + /// + public void UseDefaultProxy() + { + //用长度为0的字符串来设置 + if (!SetConfig(Un4seen.Bass.BASSConfig.BASS_CONFIG_NET_PROXY, string.Empty)) + { + throw new Exception("设置代理失败:" + Un4seen.Bass.Bass.BASS_ErrorGetCode()); + } + } + + /// + /// 不使用任何代理服务器 + /// + public void DontUseProxy() + { + bool result = SetConfig(Un4seen.Bass.BASSConfig.BASS_CONFIG_NET_PROXY, null); + if (!result) + { + //bass.dll中BASS_SetConfigPtr函数返回的其实是代理字符串指针,所以设置为NULL时会返回NULL,被Bass.Net封装后就永远返回false。 + //throw new Exception("设置代理失败:" + Un4seen.Bass.Bass.BASS_ErrorGetCode()); + } + } + + /// + /// Sets the download rate restriction. + /// + /// if set to true the download rate restriction is enabled. + public void SetDownloadRateRestriction(bool isEnabled) + { + if (isEnabled) + { + openUrlConfig |= Un4seen.Bass.BASSFlag.BASS_STREAM_RESTRATE; + } + else + { + openUrlConfig &= ~Un4seen.Bass.BASSFlag.BASS_STREAM_RESTRATE; + } + } + + #endregion + + #region Event Handleres + /// + /// 更新播放进度 + /// + private void positionTimer_Tick(object sender, EventArgs e) + { + if (ActiveStreamHandle == 0) + { + ChannelPosition = TimeSpan.Zero; + } + else + { + inChannelTimerUpdate = true; + ChannelPosition = TimeSpan.FromSeconds(Un4seen.Bass.Bass.BASS_ChannelBytes2Seconds(ActiveStreamHandle, Un4seen.Bass.Bass.BASS_ChannelGetPosition(ActiveStreamHandle, 0))); + inChannelTimerUpdate = false; + } + } + #endregion + + #region Private Utility Methods + /// + /// 查找设备的序号 + /// + /// 要查找的设备 + /// 当找不到设备时,是否返回默认设备的序号 + /// + private static int FindDevice(DeviceInfo? device, bool returnDefault = false) + { + + + if (device.HasValue) + { + int deviceNO = -1; + var devices = Un4seen.Bass.Bass.BASS_GetDeviceInfos(); + var filteredDevices = from d in devices where d.id != null && d.id == device.Value.ID select Array.IndexOf(devices, d); + if (filteredDevices.Count() == 1) + { + deviceNO = filteredDevices.First(); + } + if (deviceNO == -1) + { + filteredDevices = from d in devices where d.name == device.Value.Name select Array.IndexOf(devices, d); + if (filteredDevices.Count() == 1) + { + deviceNO = filteredDevices.First(); + } + } + if (deviceNO == -1) + { + filteredDevices = from d in devices where d.driver == device.Value.Driver select Array.IndexOf(devices, d); + if (filteredDevices.Count() == 1) + { + deviceNO = filteredDevices.First(); + } + } + if (deviceNO == -1 && returnDefault) + { + return FindDefaultDevice(); + } + else if (deviceNO != -1) + { + return deviceNO; + } + else + { + throw new Exception("找不到此设备:" + device.Value.Name); + } + } + else + { + return FindDefaultDevice(); + } + } + + /// + /// 返回默认设备的序号 + /// + /// + private static int FindDefaultDevice() + { + var devices = Un4seen.Bass.Bass.BASS_GetDeviceInfos(); + for (int i = 0; i < devices.Length; ++i) + { + if (devices[i].IsDefault) return i; + } + throw new Exception("没有默认设备"); + } + + /// + /// 初始化BassEngine + /// + private void Initialize(DeviceInfo? device = null) + { + positionTimer.Interval = TimeSpan.FromSeconds(double.Parse(ConfigurationManager.AppSettings["Bass.ChannelPositionRefreshRate"])); + positionTimer.Tick += positionTimer_Tick; + + IsPlaying = false; + + IntPtr handle = IntPtr.Zero; + if (Application.Current.MainWindow != null) + { + handle = new WindowInteropHelper(Application.Current.MainWindow).EnsureHandle(); + } + + int deviceNO = FindDevice(device, true); + if (!Un4seen.Bass.Bass.BASS_Init(deviceNO, sampleFrequency, initFlags, handle)) + { + var error = Un4seen.Bass.Bass.BASS_ErrorGetCode(); + int count = Un4seen.Bass.Bass.BASS_GetDeviceCount(); + for (deviceNO = -1; deviceNO < count; ++deviceNO) + { + if (deviceNO != 0 && Un4seen.Bass.Bass.BASS_Init(deviceNO, sampleFrequency, initFlags, handle)) + { + break; + } + } + if (deviceNO == count) + { + throw new BassInitializationFailureException(error); + } + } + + if (device == null && deviceNO == FindDefaultDevice()) + { + Device = null; + } + else + { + var info = Un4seen.Bass.Bass.BASS_GetDeviceInfo(Un4seen.Bass.Bass.BASS_GetDevice()); + Device = new DeviceInfo { Driver = info.driver, Name = info.name, ID = info.id }; + } + } + + /// + /// 播放当前流 + /// + private void PlayCurrentStream() + { + // Play Stream + if (ActiveStreamHandle != 0 && Un4seen.Bass.Bass.BASS_ChannelPlay(ActiveStreamHandle, false)) + { + Un4seen.Bass.BASS_CHANNELINFO info = new Un4seen.Bass.BASS_CHANNELINFO(); + Un4seen.Bass.Bass.BASS_ChannelGetInfo(ActiveStreamHandle, info); + } +#if DEBUG + else + { + + Debug.WriteLine("Error={0}", Un4seen.Bass.Bass.BASS_ErrorGetCode()); + + } +#endif + } + /// + /// 释放当前流 + /// + private void FreeCurrentStream() + { + if (onlineFileWorker != null) + { + onlineFileWorker.Abort(); + onlineFileWorker = null; + } + + if (ActiveStreamHandle != 0) + { + if (!Un4seen.Bass.Bass.BASS_StreamFree(ActiveStreamHandle)) + { + Debug.WriteLine("BASS_StreamFree失败:" + Un4seen.Bass.Bass.BASS_ErrorGetCode()); + } + //Debug.WriteLine("已调用BASS_StreamFree()"); + ActiveStreamHandle = 0; + } + } + /// + /// 设置音量 + /// + private void SetVolume() + { + if (ActiveStreamHandle != 0) + { + float realVolume = IsMuted ? 0 : (float)Volume; + Un4seen.Bass.Bass.BASS_ChannelSetAttribute(ActiveStreamHandle, Un4seen.Bass.BASSAttribute.BASS_ATTRIB_VOL, realVolume); + } + } + + /// + /// Set a config with string value type. + /// + /// config name + /// string value + /// success or not + private static bool SetConfig(Un4seen.Bass.BASSConfig name, string value) + { + string nameString = name.ToString(); + if (stringHandles.ContainsKey(nameString) && stringHandles[nameString] != IntPtr.Zero) + { + Marshal.FreeHGlobal(stringHandles[nameString]); + stringHandles.Remove(nameString); + } + + var handle = value == null ? IntPtr.Zero : Marshal.StringToHGlobalAnsi(value); + if (Un4seen.Bass.Bass.BASS_SetConfigPtr(name, handle)) + { + if (handle != IntPtr.Zero) + { + stringHandles[nameString] = handle; + } + return true; + } + if (handle != IntPtr.Zero) + { + Marshal.FreeHGlobal(handle); + } + return false; + } + + /// + /// Set configs presented as a string. + /// + /// The configs. + /// + /// + /// + /// + private static void SetConfigs(string configs) + { + foreach (var config in configs.Split('|')) + { + if (config == string.Empty) continue; + + var spaceIndex = config.IndexOf(' '); + if (spaceIndex == -1) + { + throw new InvalidDataException(string.Format("Config 'Bass.SetConfigOnInitialization' is invalid. Invalid config string: {0}", config)); + } + var configNameString = config.Substring(0, spaceIndex); + Un4seen.Bass.BASSConfig configName; + if (!Un4seen.Bass.BASSConfig.TryParse(configNameString, out configName) + || !Enum.IsDefined(typeof(Un4seen.Bass.BASSConfig), configName)) + { + throw new InvalidDataException(string.Format("Config 'Bass.SetConfigOnInitialization' is invalid. Invalid config name: {0}", configNameString)); + } + + var configValueString = config.Substring(spaceIndex + 1); + int configValueInt; + if (int.TryParse(configValueString, out configValueInt)) + { + if (!Un4seen.Bass.Bass.BASS_SetConfig(configName, configValueInt)) + { + throw new Exception(string.Format("Set config {0} with value {1} failed. Error code {2}", + configName, configValueInt, Un4seen.Bass.Bass.BASS_ErrorGetCode())); + } + continue; + } + bool configValueBool; + if (bool.TryParse(configValueString, out configValueBool)) + { + if (!Un4seen.Bass.Bass.BASS_SetConfig(configName, configValueBool)) + { + throw new Exception(string.Format("Set config {0} with value {1} failed. Error code {2}", + configName, configValueBool, Un4seen.Bass.Bass.BASS_ErrorGetCode())); + } + continue; + } + if (!SetConfig(configName, configValueString)) + { + throw new Exception(string.Format("Set config {0} with value {1} failed. Error code {2}", + configName, configValueString, Un4seen.Bass.Bass.BASS_ErrorGetCode())); + } + } + } + #endregion + + #region Callbacks + /// + /// 播放完毕 + /// + private void EndTrack(int handle, int channel, int data, IntPtr user) + { + Application.Current.Dispatcher.BeginInvoke(new Action(() => + { + Stop(); + RaiseTrackEndedEvent(); + })); + } + #endregion + + #region Public Properties + /// + /// 长度 + /// + public TimeSpan ChannelLength + { + get { return channelLength; } + protected set + { + TimeSpan oldValue = channelLength; + channelLength = value; + if (oldValue != channelLength) + NotifyPropertyChanged("ChannelLength"); + } + } + + /// + /// 位置 + /// + public TimeSpan ChannelPosition + { + get { return currentChannelPosition; } + set + { + if (!inChannelSet) + { + inChannelSet = true; // Avoid recursion + TimeSpan oldValue = currentChannelPosition; + TimeSpan position = value; + if (position > ChannelLength) position = ChannelLength; + if (position < TimeSpan.Zero) position = TimeSpan.Zero; + if (!inChannelTimerUpdate) + Un4seen.Bass.Bass.BASS_ChannelSetPosition(ActiveStreamHandle, Un4seen.Bass.Bass.BASS_ChannelSeconds2Bytes(ActiveStreamHandle, position.TotalSeconds)); + currentChannelPosition = position; + if (oldValue != currentChannelPosition) + NotifyPropertyChanged("ChannelPosition"); + inChannelSet = false; + } + } + } + + /// + /// 当前流的句柄 + /// + public int ActiveStreamHandle + { + get { return activeStreamHandle; } + protected set + { + int oldValue = activeStreamHandle; + activeStreamHandle = value; + if (oldValue != activeStreamHandle) + { + if (activeStreamHandle != 0) + { + SetVolume(); + } + NotifyPropertyChanged("ActiveStreamHandle"); + } + } + } + + /// + /// 可以使用播放命令 + /// + public bool CanPlay + { + get { return canPlay; } + protected set + { + bool oldValue = canPlay; + canPlay = value; + if (oldValue != canPlay) + NotifyPropertyChanged("CanPlay"); + } + } + + /// + /// 可以使用暂停命令 + /// + public bool CanPause + { + get { return canPause; } + protected set + { + bool oldValue = canPause; + canPause = value; + if (oldValue != canPause) + NotifyPropertyChanged("CanPause"); + } + } + + /// + /// 可以使用停止命令 + /// + public bool CanStop + { + get { return canStop; } + protected set + { + bool oldValue = canStop; + canStop = value; + if (oldValue != canStop) + NotifyPropertyChanged("CanStop"); + } + } + + /// + /// 是否正在播放 + /// + public bool IsPlaying + { + get { return isPlaying; } + protected set + { + bool oldValue = isPlaying; + isPlaying = value; + if (oldValue != isPlaying) + NotifyPropertyChanged("IsPlaying"); + positionTimer.IsEnabled = value; + } + } + + /// + /// 音量 + /// + public double Volume + { + get { return volume; } + set + { + value = Math.Max(0, Math.Min(1, value)); + if (volume != value) + { + volume = value; + SetVolume(); + NotifyPropertyChanged("Volume"); + } + } + } + + /// + /// 是否静音 + /// + public bool IsMuted + { + get { return isMuted; } + set + { + if (isMuted != value) + { + isMuted = value; + SetVolume(); + NotifyPropertyChanged("IsMuted"); + } + } + } + + /// + /// 设备(空代表默认设备) + /// + public DeviceInfo? Device { get; private set; } + #endregion + + #region Events + /// + /// 当播放完毕时发生。 + /// + public event EventHandler TrackEnded; + + /// + /// 引发播放完毕事件 + /// + void RaiseTrackEndedEvent() + { + if (TrackEnded != null) + TrackEnded(this, EventArgs.Empty); + } + + /// + /// 当打开音频文件失败时发生。 + /// + public event EventHandler OpenFailed; + + /// + /// 引发打开音频文件失败事件 + /// + void RaiseOpenFailedEvent() + { + if (OpenFailed != null) + OpenFailed(this, EventArgs.Empty); + } + + /// + /// 当打开音频文件成功时发生。 + /// + public event EventHandler OpenSucceeded; + + /// + /// 引发打开音频文件成功事件 + /// + void RaiseOpenSucceededEvent() + { + if (OpenSucceeded != null) + OpenSucceeded(this, EventArgs.Empty); + } + #endregion + + #region ISpectrumPlayer + public bool GetFFTData(float[] fftDataBuffer) + { + return (Un4seen.Bass.Bass.BASS_ChannelGetData(ActiveStreamHandle, fftDataBuffer, maxFFT)) > 0; + } + + public int GetFFTFrequencyIndex(int frequency) + { + return Un4seen.Bass.Utils.FFTFrequency2Index(frequency, getFFTFrequencyIndexLength, sampleFrequency); + } + #endregion + } +} \ No newline at end of file diff --git a/DoubanFM.Bass/BassInitializationFailureException.cs b/DoubanFM.Bass/BassInitializationFailureException.cs new file mode 100644 index 0000000..472ff82 --- /dev/null +++ b/DoubanFM.Bass/BassInitializationFailureException.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DoubanFM.Bass +{ + public class BassInitializationFailureException : Exception + { + public Un4seen.Bass.BASSError Code { get; private set; } + + public static string GetErrorMessage(Un4seen.Bass.BASSError code) + { + StringBuilder sb = new StringBuilder(); + sb.Append("音频组件初始化失败: "); + string detail = null; + switch (code) + { + case Un4seen.Bass.BASSError.BASS_ERROR_DX: + detail = "未安装DirectX。"; + break; + case Un4seen.Bass.BASSError.BASS_ERROR_DEVICE: + detail = "无效的设备。"; + break; + case Un4seen.Bass.BASSError.BASS_ERROR_ALREADY: + detail = "设备已经初始化。"; + break; + case Un4seen.Bass.BASSError.BASS_ERROR_DRIVER: + detail = "没有可用的设备驱动,设备可能正在使用。"; + break; + case Un4seen.Bass.BASSError.BASS_ERROR_FORMAT: + detail = "设备不支持此格式。"; + break; + case Un4seen.Bass.BASSError.BASS_ERROR_MEM: + detail = "内存不足。"; + break; + case Un4seen.Bass.BASSError.BASS_ERROR_NO3D: + detail = "无法初始化3D支持。"; + break; + case Un4seen.Bass.BASSError.BASS_ERROR_UNKNOWN: + default: + detail = "未知错误。"; + break; + } + sb.Append(detail); + return sb.ToString(); + } + + public BassInitializationFailureException(Un4seen.Bass.BASSError code) + : base(GetErrorMessage(code)) + { + Code = code; + } + } +} diff --git a/DoubanFM.Bass/DeviceInfo.cs b/DoubanFM.Bass/DeviceInfo.cs new file mode 100644 index 0000000..8f7fda3 --- /dev/null +++ b/DoubanFM.Bass/DeviceInfo.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DoubanFM.Bass +{ + [Serializable] + public struct DeviceInfo + { + public string Driver { get; set; } + public string ID { get; set; } + public string Name { get; set; } + + public override string ToString() + { + return Name; + } + } +} diff --git a/DoubanFM.Bass/DoubanFM.Bass.csproj b/DoubanFM.Bass/DoubanFM.Bass.csproj new file mode 100644 index 0000000..a1f4e2c --- /dev/null +++ b/DoubanFM.Bass/DoubanFM.Bass.csproj @@ -0,0 +1,83 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {62324CFD-03FF-44B4-9204-66BAE86972B6} + Library + Properties + DoubanFM.Bass + DoubanFM.Bass + v4.0 + 512 + Client + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + false + + + + + + + + + + + ..\WPFSoundVisualizationLib.dll + + + + + + + + + + + Always + + + + Always + + + Always + + + + + Always + + + Always + + + + + \ No newline at end of file diff --git a/DoubanFM.Bass/Properties/AssemblyInfo.cs b/DoubanFM.Bass/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..ce8ef64 --- /dev/null +++ b/DoubanFM.Bass/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的常规信息通过以下 +// 特性集控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("DoubanFM.Bass")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DoubanFM.Bass")] +[assembly: AssemblyCopyright("Copyright © 2012")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +// 将 ComVisible 设置为 false 使此程序集中的类型 +// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, +// 则将该类型上的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("264e77f8-e37c-4e08-8d15-5e82dd398bcc")] +// 程序集的版本信息由下面四个值组成: +// +// 主版本 +// 次版本 +// 内部版本号 +// 修订号 +// +// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, +// 方法是按如下所示使用“*”: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("2.1.4.0")] +//[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/DoubanFM.Bass/x64/bass.dll b/DoubanFM.Bass/x64/bass.dll new file mode 100644 index 0000000..9bfd66a Binary files /dev/null and b/DoubanFM.Bass/x64/bass.dll differ diff --git a/DoubanFM.Bass/x64/plugins/bass_aac.dll b/DoubanFM.Bass/x64/plugins/bass_aac.dll new file mode 100644 index 0000000..1d37a11 Binary files /dev/null and b/DoubanFM.Bass/x64/plugins/bass_aac.dll differ diff --git a/DoubanFM.Bass/x86/bass.dll b/DoubanFM.Bass/x86/bass.dll new file mode 100644 index 0000000..963bea5 Binary files /dev/null and b/DoubanFM.Bass/x86/bass.dll differ diff --git a/DoubanFM.Bass/x86/plugins/bass_aac.dll b/DoubanFM.Bass/x86/plugins/bass_aac.dll new file mode 100644 index 0000000..2da3043 Binary files /dev/null and b/DoubanFM.Bass/x86/plugins/bass_aac.dll differ diff --git a/DoubanFM.Core/ChannelSearch/ChannelSearch.cs b/DoubanFM.Core/ChannelSearch/ChannelSearch.cs new file mode 100644 index 0000000..e99f860 --- /dev/null +++ b/DoubanFM.Core/ChannelSearch/ChannelSearch.cs @@ -0,0 +1,346 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows; +using System.Threading; +using System.Diagnostics; + +namespace DoubanFM.Core +{ + /// + /// 提供音乐搜索的功能 + /// + public class ChannelSearch : DependencyObject + { + #region 依赖项属性 + + public static readonly DependencyProperty IsSearchFinishedProperty = DependencyProperty.Register("IsSearchFinished", typeof(bool), typeof(ChannelSearch), new PropertyMetadata(true)); + public static readonly DependencyProperty IsPreviousPageEnabledProperty = DependencyProperty.Register("IsPreviousPageEnabled", typeof(bool), typeof(ChannelSearch)); + public static readonly DependencyProperty IsNextPageEnabledProperty = DependencyProperty.Register("IsNextPageEnabled", typeof(bool), typeof(ChannelSearch)); + public static readonly DependencyProperty ShowNoResultHintProperty = DependencyProperty.Register("ShowNoResultHint", typeof(bool), typeof(ChannelSearch), new PropertyMetadata(true)); + public static readonly DependencyProperty SearchResultProperty = DependencyProperty.Register("SearchResult", typeof(IEnumerable), typeof(ChannelSearch)); + + #endregion + + #region 属性 + + /// + /// 获取一个值,该值指示是否搜索完成 + /// + public bool IsSearchFinished + { + get { return (bool)GetValue(IsSearchFinishedProperty); } + private set + { + if (IsSearchFinished != value) + { + bool last = IsSearchFinished; + SetValue(IsSearchFinishedProperty, value); + SetValue(ShowNoResultHintProperty, IsSearchFinished && (SearchResult == null || SearchResult.Count() == 0)); + if (value == true) + RaiseSearchFinishedEvent(); + } + } + } + /// + /// 获取搜索结果 + /// + public IEnumerable SearchResult + { + get { return (IEnumerable)GetValue(SearchResultProperty); } + private set + { + SetValue(SearchResultProperty, value); + SetValue(ShowNoResultHintProperty, IsSearchFinished && (SearchResult == null || SearchResult.Count() == 0)); + } + } + /// + /// 获取上一页是否可用 + /// + public bool IsPreviousPageEnabled { get { return (bool)GetValue(IsPreviousPageEnabledProperty); } } + /// + /// 获取下一页是否可用 + /// + public bool IsNextPageEnabled { get { return (bool)GetValue(IsNextPageEnabledProperty); } } + private string _previousPageLink; + /// + /// 上一页的链接 + /// + private string PreviousPageLink + { + get { return _previousPageLink; } + set + { + _previousPageLink = value; + SetValue(IsPreviousPageEnabledProperty, !string.IsNullOrEmpty(_previousPageLink)); + } + } + private string _nextPageLink; + /// + /// 下一页的链接 + /// + private string NextPageLink + { + get { return _nextPageLink; } + set + { + _nextPageLink = value; + SetValue(IsNextPageEnabledProperty, !string.IsNullOrEmpty(_nextPageLink)); + } + } + /// + /// 是否显示没有搜索结果的提示 + /// + public bool ShowNoResultHint + { + get { return (bool)GetValue(ShowNoResultHintProperty); } + } + /// + /// 设置 + /// + public Settings Settings { get; private set; } + + #endregion + + #region 成员变量 + + /// + /// 获取搜索文本 + /// + string _searchText; + /// + /// 搜索第几页 + /// + int _page; + + #endregion + + internal ChannelSearch(Settings settings) + :base() + { + Settings = settings; + } + + #region 事件 + + /// + /// 当搜索完成时发生。 + /// + public event EventHandler SearchFinished; + /// + /// 触发SearchFinished事件。 + /// + private void RaiseSearchFinishedEvent() + { + if (SearchFinished != null) + SearchFinished(this, EventArgs.Empty); + } + + #endregion + + #region 搜索操作 + + /// + /// 开始新搜索 + /// + /// 搜索内容 + public void StartSearch(string text) + { + _searchText = text; + _page = 1; + Search(); + } + /// + /// 上一页 + /// + public void PreviousPage() + { + --_page; + Search(); + } + + /// + /// 下一页 + /// + public void NextPage() + { + ++_page; + Search(); + } + + #endregion + + #region 成员方法 + + /// + /// 搜索 + /// + /// 搜索文本 + /// Start值 + void Search() + { + if (IsSearchFinished == false)return; + SearchResult = null; + IsSearchFinished = false; + PreviousPageLink = null; + NextPageLink = null; + ThreadPool.QueueUserWorkItem(new WaitCallback((state)=> + { + //构造链接 + Parameters parameters = new Parameters(); + parameters["start"] = ((_page - 1) * 15).ToString(); + parameters["search_text"] = _searchText; + string url = ConnectionBase.ConstructUrlWithParameters("http://music.douban.com/subject_search", parameters); + + //获取网页 + ConnectionBase connection= new ConnectionBase(true); + string file = string.Empty; + try + { + file = connection.Get(url); + } + catch (Exception ex) + { + Debug.WriteLine(ex); + file = new ConnectionBase().Get("http://music.douban.com"); + file = new ConnectionBase().Get(url); + } + + var searhResult = GetSearchItems(file); + var previous = GetPreviousPageLink(file); + var next = GetNextPageLink(file); + Dispatcher.Invoke(new Action(() => + { + SearchResult = searhResult; + PreviousPageLink = previous; + NextPageLink = next; + IsSearchFinished = true; + })); + })); + } + /// + /// 获取搜索的结果 + /// + /// + private IEnumerable GetSearchItems(string file) + { + List items = new List(); + try + { + bool isSearchFilterEnabled = true; + Dispatcher.Invoke(new Action(() => { isSearchFilterEnabled = Settings.IsSearchFilterEnabled; })); + + //找出艺术家 + MatchCollection mc = Regex.Matches(file, @"
.*?", RegexOptions.IgnoreCase | RegexOptions.Singleline); + foreach(Match mm in mc) + { + string temp = mm.Groups[0].Value; + string titleTemp = Regex.Match(temp, @"", RegexOptions.IgnoreCase | RegexOptions.Singleline).Groups[0].Value; + string title = Regex.Match(titleTemp, @".*?title=\""([^\""]+)\""", RegexOptions.IgnoreCase | RegexOptions.Singleline).Groups[1].Value; + string link = Regex.Match(titleTemp, @".*?href=\""([^\""]+)\""", RegexOptions.IgnoreCase | RegexOptions.Singleline).Groups[1].Value; + string pictureTemp = Regex.Match(temp, @"", RegexOptions.IgnoreCase | RegexOptions.Singleline).Groups[0].Value; + string picture = Regex.Match(pictureTemp, @".*?src=\""([^\""]+)\""", RegexOptions.IgnoreCase | RegexOptions.Singleline).Groups[1].Value; + Match ma = Regex.Match(temp, @".*?href=\""http://douban\.fm/\?context=([^\""]+)\""", RegexOptions.IgnoreCase | RegexOptions.Singleline); + string context = null; + if (ma != null) context = ma.Groups[1].Value; + ChannelSearchItem item = new ChannelSearchItem(title, picture, link, null, true, context); + if (!isSearchFilterEnabled || !string.IsNullOrEmpty(item.Context)) + items.Add(item); + } + + //找出专辑 + mc = Regex.Matches(file, @"]*?class=\""item\""[^<>]*?>.*?", RegexOptions.IgnoreCase | RegexOptions.Singleline); + foreach (Match mm in mc) + { + string temp = mm.Groups[0].Value; + string titleTemp = Regex.Match(temp, @"]*?class=\""nbg\""[^<>]*?/?>", RegexOptions.IgnoreCase | RegexOptions.Singleline).Groups[0].Value; + string subject = Regex.Match(titleTemp, @"href=\""[^<>]*?subject/(\d+)", RegexOptions.IgnoreCase | RegexOptions.Singleline).Groups[1].Value; + string title = Regex.Match(titleTemp, @"title=\""([^\""]+)\""", RegexOptions.IgnoreCase | RegexOptions.Singleline).Groups[1].Value; + string link = Regex.Match(titleTemp, @"href=\""([^\""]+)\""", RegexOptions.IgnoreCase | RegexOptions.Singleline).Groups[1].Value; + string pictureTemp = Regex.Match(temp, @"]*?/?>", RegexOptions.IgnoreCase | RegexOptions.Singleline).Groups[0].Value; + string picture = Regex.Match(pictureTemp, @"src=\""([^\""]+)\""", RegexOptions.IgnoreCase | RegexOptions.Singleline).Groups[1].Value; + Match ma = Regex.Match(temp, @"href=\""http://douban\.fm/\?context=([^\""]+)\""", RegexOptions.IgnoreCase | RegexOptions.Singleline); + + string context = null; + if (ma.Success) context = ma.Groups[1].Value; + if (string.IsNullOrEmpty(context)) + { + context = MakeContext(subject); + } + + ChannelSearchItem item = new ChannelSearchItem(title, picture, link, null, false, context); + if (!isSearchFilterEnabled || !string.IsNullOrEmpty(item.Context)) + items.Add(item); + } + } + catch { } + + return items; + } + private static string MakeContext(string subject) + { + try + { + string file = new ConnectionBase().Get("http://api.douban.com/music/subject/" + subject); + if (file != null) + { + MatchCollection mc = Regex.Matches(file, @"]*index=""\d+""[^>]*>", RegexOptions.IgnoreCase | RegexOptions.Singleline); + foreach (Match ma in mc) + { + if (ma.Success) + { + Match ma2 = Regex.Match(ma.Value, @"name=\""tracks?\""", RegexOptions.IgnoreCase | RegexOptions.Singleline); + if (ma2.Success) + { + return "channel:0|subject_id:" + subject; + } + } + } + } + } + catch { } + return null; + } + + /// + /// 获取上一页的链接 + /// + /// + private static string GetPreviousPageLink(string file) + { + try + { + Match mc = Regex.Match(file, @".*?", RegexOptions.IgnoreCase | RegexOptions.Multiline); + Match mc2 = Regex.Match(mc.Groups[0].Value, @" + /// 获取下一页的链接 + /// + /// + private static string GetNextPageLink(string file) + { + try + { + Match mc = Regex.Match(file, @".*?", RegexOptions.IgnoreCase | RegexOptions.Multiline); + Match mc2 = Regex.Match(mc.Groups[0].Value, @" + /// 搜索结果中的项 + /// + public class ChannelSearchItem + { + /// + /// 标题 + /// + public string Title { get; private set; } + /// + /// 图片 + /// + public string Picture { get; private set; } + /// + /// 链接 + /// + public string Link { get; private set; } + /// + /// 其他信息 + /// + public string[] Infomations { get; private set; } + /// + /// 是否是艺术家 + /// + public bool IsArtist { get; private set; } + /// + /// 上下文 + /// + public string Context { get; private set; } + /// + /// 能否收听此项 + /// + public bool CanContextPlay + { + get { return Context != null && Context.Length > 0; } + } + + /// + /// 生成 class 的新实例。 + /// + /// 标题 + /// 图片 + /// 链接 + /// 其他信息 + /// 是否是艺术家 + /// 上下文 + internal ChannelSearchItem(string title, string picture, string link, string[] infomations, bool isArtist, string context) + { + Title = title; + Picture = picture; + Link = link; + Infomations = infomations; + IsArtist = isArtist; + Context = context; + } + + /// + /// 返回一个频道 + /// + /// + public Channel GetChannel() + { + if (CanContextPlay) return new Channel(Channel.PersonalId, Title, Context); + else return null; + } + } +} diff --git a/DoubanFM.Core/ConnectionBase.cs b/DoubanFM.Core/ConnectionBase.cs new file mode 100644 index 0000000..39717ae --- /dev/null +++ b/DoubanFM.Core/ConnectionBase.cs @@ -0,0 +1,376 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.IO.Compression; +using System.Linq; +using System.Runtime.InteropServices.ComTypes; +using System.Text; +using System.Net; +using System.IO; +using System.IO.IsolatedStorage; +using System.Runtime.Serialization.Formatters.Binary; +using System.Runtime.Serialization; +using System.Diagnostics; + +namespace DoubanFM.Core +{ + /// + /// 网络连接基础类 + /// + public class ConnectionBase + { + /// + /// Cookie + /// + public static CookieContainer Cookie; + /// + /// 默认HTTP头:UserAgent + /// + public static string DefaultUserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"; + /// + /// 默认HTTP头:accept + /// + public static string DefaultAccept = "text/html, application/xhtml+xml, */*"; + /// + /// 默认HTTP头:contentType + /// + public static string DefaultContentType = "application/x-www-form-urlencoded"; + /// + /// 默认编码 + /// + public static Encoding DefaultEncoding = Encoding.UTF8; + /// + /// 你懂的…… + /// + public string UserAgent, Accept, ContentType; + /// + /// 编码 + /// + public Encoding Encoding; + /// + /// 是否抛出异常 + /// + public bool ThrowException; + /// + /// 是否使用Gzip编码 + /// + public bool UseGzip = true; + /// + /// 数据保存文件夹 + /// + public static readonly string DataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"K.F.Storm\豆瓣电台"); + + static ConnectionBase() + { + if (!LoadCookies()) ClearCookie(); + } + + public ConnectionBase(bool throwException, string userAgent, string accept, string contentType, Encoding encoding) + { + ThrowException = throwException; + UserAgent = userAgent; + Accept = accept; + ContentType = contentType; + Encoding = encoding; + } + + public ConnectionBase(bool throwException = false) + : this(DefaultEncoding, throwException) + { + } + + public ConnectionBase(Encoding encoding, bool throwException = false) + : this(throwException, DefaultUserAgent, DefaultAccept, DefaultContentType, encoding) + { + } + /// + /// 用Post方法发送请求 + /// + /// 请求的地址 + /// Accept头 + /// Referer头 + /// ContentType头 + /// 请求正文 + /// + /// 响应正文 + /// + public string Post(string postUri, string accept, string referer, string contentType, byte[] content) + { + string file = null; + + try + { + HttpWebRequest request = WebRequest.Create(postUri) as HttpWebRequest; + request.Accept = accept; + request.AllowAutoRedirect = true; + request.ContentLength = content.Length; + request.ContentType = contentType; + request.CookieContainer = Cookie; + request.KeepAlive = true; + request.Method = "POST"; + request.Referer = referer; + request.UserAgent = UserAgent; + request.ServicePoint.Expect100Continue = false; + if (UseGzip) + { + request.Headers["Accept-Encoding"] = "gzip, deflate"; + } + using (var requestStream = request.GetRequestStream()) + requestStream.Write(content, 0, content.Length); + using (var response = request.GetResponse() as HttpWebResponse) + { + var stream = response.GetResponseStream(); + if (response.ContentEncoding.ToLower().Contains("gzip")) + { + stream = new GZipStream(stream, CompressionMode.Decompress); + } + using (var sr = new StreamReader(stream, Encoding)) + { + file = sr.ReadToEnd(); + } + } + } + catch (Exception ex) + { + Debug.WriteLine(ex); + if (ThrowException) + throw; + } + + return file; + } + /// + /// 用Post方法发送请求 + /// + /// 请求的地址 + /// 请求正文 + /// 响应正文 + public string Post(string postUri, byte[] content) + { + return Post(postUri, null, content); + } + /// + /// 用Post方法发送请求 + /// + /// 请求的地址 + /// Referer头 + /// 请求正文 + /// 响应正文 + public string Post(string postUri, string referer, byte[] content) + { + return Post(postUri, Accept, referer, ContentType, content); + } + /// + /// 用Get方法发送请求 + /// + /// 请求的地址 + /// Accept头 + /// Referer头 + /// + /// 响应正文 + /// + public string Get(string getUri, string accept, string referer) + { + string file = null; + + try + { + HttpWebRequest request = WebRequest.Create(getUri) as HttpWebRequest; + request.Accept = accept; + request.AllowAutoRedirect = true; + request.CookieContainer = Cookie; + request.KeepAlive = true; + request.Method = "GET"; + request.Referer = referer; + request.UserAgent = UserAgent; + if (UseGzip) + { + request.Headers["Accept-Encoding"] = "gzip, deflate"; + } + using (var response = request.GetResponse() as HttpWebResponse) + { + var stream = response.GetResponseStream(); + if (response.ContentEncoding.ToLower().Contains("gzip")) + { + stream = new GZipStream(stream, CompressionMode.Decompress); + } + using (var sr = new StreamReader(stream, Encoding)) + { + file = sr.ReadToEnd(); + } + } + } + catch (Exception ex) + { + Debug.WriteLine(ex); + if (ThrowException) + throw; + } + + return file; + } + /// + /// 用Get方法发送请求 + /// + /// 请求的地址 + /// 响应正文 + public string Get(string getUri) + { + return Get(getUri, Accept, null); + } + + /// + /// 用Get方法发送请求 + /// + /// 请求的地址 + /// Referer头 + /// 响应正文 + public string Get(string getUri, string referer) + { + return Get(getUri, Accept, referer); + } + /// + /// 读取Cookies + /// + /// 成功与否 + public static bool LoadCookies() + { + try + { + using (FileStream stream = File.OpenRead(Path.Combine(DataFolder, "cookies.dat"))) + { + BinaryFormatter formatter = new BinaryFormatter(); + Cookie = (CookieContainer)formatter.Deserialize(stream); + } + } + catch + { + return false; + } + return true; + } + /// + /// 保存Cookies + /// + /// 成功与否 + public static bool SaveCookies() + { + try + { + if (!Directory.Exists(DataFolder)) + Directory.CreateDirectory(DataFolder); + using (FileStream stream = File.OpenWrite(Path.Combine(DataFolder, "cookies.dat"))) + { + BinaryFormatter formatter = new BinaryFormatter(); + formatter.Serialize(stream, Cookie); + } + } + + catch + { + return false; + } + + return true; + } + /// + /// 根据请求的URL和参数构造一个新的URL + /// + /// 请求URL + /// 参数 + /// 新的URL + public static string ConstructUrlWithParameters(string baseUrl, Parameters parameters) + { + if (parameters == null || parameters.Count() == 0) + return baseUrl; + return baseUrl + "?" + parameters; + } + + /// + /// 清除Cookie + /// + public static void ClearCookie() + { + Cookie = new CookieContainer(1000, 1000, 100000); + } + + /// + /// 设置代理服务器 + /// + /// 主机 + /// 端口 + /// 用户名 + /// 密码 + public static void SetProxy(string host, int port, string username = null, string password = null) + { + if (string.IsNullOrEmpty(host)) + throw new ArgumentException("主机不能为空", "host"); + if (string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password)) + throw new ArgumentException("填写密码后用户名不能为空", "username"); + if (string.IsNullOrEmpty(password) && !string.IsNullOrEmpty(username)) + throw new ArgumentException("填写用户名后密码不能为空", "password"); + WebRequest.DefaultWebProxy = new WebProxy(host, port); + if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password)) + { + WebRequest.DefaultWebProxy.Credentials = new NetworkCredential(username, password); + } + } + /// + /// 使用默认代理 + /// + public static void UseDefaultProxy() + { + WebRequest.DefaultWebProxy = WebRequest.GetSystemWebProxy(); + } + + /// + /// 不使用任何代理服务器设置 + /// + public static void DontUseProxy() + { + WebRequest.DefaultWebProxy = null; + } + } + + /// + /// 代表URL地址中的参数 + /// + public class Parameters : Dictionary + { + /// + /// 是否添加空参数 + /// + public bool AddEmptyParameter { get; set; } + + /// + /// 生成 class 的新实例。 + /// + /// 是否添加空参数 + public Parameters(bool addEmptyParameter = false) + :base() + { + AddEmptyParameter = addEmptyParameter; + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + foreach (var p in this) + { + if (AddEmptyParameter || !string.IsNullOrEmpty(p.Value)) + { + if (sb.Length != 0) sb.Append("&"); + sb.Append(Uri.EscapeDataString(p.Key)); + sb.Append("="); + sb.Append(Uri.EscapeDataString(p.Value == null ? string.Empty : p.Value)); + } + } + return sb.ToString(); + } + } +} diff --git a/DoubanFM.Core/DoubanFM.Core.csproj b/DoubanFM.Core/DoubanFM.Core.csproj new file mode 100644 index 0000000..3b43959 --- /dev/null +++ b/DoubanFM.Core/DoubanFM.Core.csproj @@ -0,0 +1,116 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {AA75B5E6-F373-49D7-B2E0-16C3E57321F7} + Library + Properties + DoubanFM.Core + DoubanFM.Core + v4.0 + 512 + Client + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Resources.resx + True + True + + + Resources.zh-CN.resx + True + True + + + + + + + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + ResXFileCodeGenerator + Resources.zh-CN.Designer.cs + + + + + {62324cfd-03ff-44b4-9204-66bae86972b6} + DoubanFM.Bass + + + + + \ No newline at end of file diff --git a/DoubanFM.Core/DownloadSearch/DownloadSearch.cs b/DoubanFM.Core/DownloadSearch/DownloadSearch.cs new file mode 100644 index 0000000..94d65b2 --- /dev/null +++ b/DoubanFM.Core/DownloadSearch/DownloadSearch.cs @@ -0,0 +1,127 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DoubanFM.Core +{ + /// + /// 提供下载搜索的功能 + /// + public static class DownloadSearch + { + /// + /// 设置 + /// + public static Settings Settings { get; internal set; } + /// + /// 搜索 + /// + /// 标题 + /// 艺术家 + /// 专辑 + public static void Search(string title, string artist, string album) + { + if (title == null) title = string.Empty; + if (artist == null) artist = string.Empty; + if (album == null) album = string.Empty; + string keyword = GetKeyword(title, artist, album); + if (Settings.DownloadSite.HasFlag(DownloadSite.BaiduMusic)) + { + BaiduMusicSearch(keyword); + } + if (Settings.DownloadSite.HasFlag(DownloadSite.QQMusic)) + { + QQMusicSearch(keyword); + } + } + + /// + /// 搜索百度音乐 + /// + /// 关键词 + private static void BaiduMusicSearch(string keyword) + { + Parameters parameters = new Parameters(); + parameters["key"] = keyword; + string url = ConnectionBase.ConstructUrlWithParameters("http://music.baidu.com/search", parameters); + UrlHelper.OpenLink(url); + } + + /// + /// 搜索QQ音乐 + /// + /// 关键词 + private static void QQMusicSearch(string keyword) + { + string url = string.Format("http://y.qq.com/#type=soso&p={0}", + Uri.EscapeDataString( + string.Format("?p=1&catZhida=1&lossless=0&t=100&utf8=1&w={0}", + Uri.EscapeDataString(keyword)))); + UrlHelper.OpenLink(url); + } + + /// + /// 获取用于搜索的关键词 + /// + /// 标题 + /// 艺术家 + /// 专辑 + /// 用于搜索的关键词 + private static string GetKeyword(string title, string artist, string album) + { + if (album.EndsWith("...")) + { + album = album.Substring(0, album.Length - 3); + } + if (Settings.TrimBrackets) + { + title = TrimBrackets(title); + artist = TrimBrackets(artist); + album = TrimBrackets(album); + } + if (Settings.SearchAlbum) + { + return string.Format("{0} {1} {2}", title, artist, album); + } + else + { + return string.Format("{0} {1}", title, artist); + } + } + + /// + /// 各种括号 + /// + private static readonly List brackets = new List { '(', '(', '[', '【'}; + + /// + /// 剔除括号内的内容 + /// + /// 任意字符串 + /// 剔除括号后的内容 + private static string TrimBrackets(string someString) + { + int index; + + foreach (var bracket in brackets) + { + index = someString.IndexOf(bracket); + if (index != -1) + { + someString = someString.Substring(0, index); + } + } + + someString = someString.Trim(); + + return someString; + } + } +} diff --git a/DoubanFM.Core/DownloadSearch/DownloadSite.cs b/DoubanFM.Core/DownloadSearch/DownloadSite.cs new file mode 100644 index 0000000..b394341 --- /dev/null +++ b/DoubanFM.Core/DownloadSearch/DownloadSite.cs @@ -0,0 +1,30 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; + +namespace DoubanFM.Core +{ + /// + /// 提供音乐下载的网站 + /// + [Flags] + public enum DownloadSite + { + /// + /// 巨鲸音乐(www.top100.cn) + /// + //Top100 = 0x1, + /// + /// 百度音乐(music.baidu.com) + /// + BaiduMusic = 0x2, + /// + /// QQ音乐(y.qq.com) + /// + QQMusic = 0x4 + } +} diff --git a/DoubanFM.Core/Encryption.cs b/DoubanFM.Core/Encryption.cs new file mode 100644 index 0000000..9301713 --- /dev/null +++ b/DoubanFM.Core/Encryption.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Security.Cryptography; +using System.IO; + +namespace DoubanFM.Core +{ + /// + /// 用于字符串加密的类 + /// + static class Encryption + { + /// + /// 加密 + /// + /// + /// + internal static string Encrypt(string rs) + { + byte[] desKey = Encoding.ASCII.GetBytes("DoubanFM"); + byte[] desIV = Encoding.ASCII.GetBytes("DoubanFM"); + + using (DESCryptoServiceProvider des = new DESCryptoServiceProvider()) + try + { + byte[] inputByteArray = Encoding.Default.GetBytes(rs); + //byte[] inputByteArray=Encoding.Unicode.GetBytes(rs); + + des.Key = desKey; // ASCIIEncoding.ASCII.GetBytes(sKey); + des.IV = desIV; //ASCIIEncoding.ASCII.GetBytes(sKey); + using (MemoryStream ms = new MemoryStream()) + using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), + CryptoStreamMode.Write)) + { + //Write the byte array into the crypto stream + //(It will end up in the memory stream) + cs.Write(inputByteArray, 0, inputByteArray.Length); + cs.FlushFinalBlock(); + + //Get the data back from the memory stream, and into a string + StringBuilder ret = new StringBuilder(); + foreach (byte b in ms.ToArray()) + { + //Format as hex + ret.AppendFormat("{0:X2}", b); + } + ret.ToString(); + return ret.ToString(); + } + } + catch + { + return rs; + } + } + + /// + /// 解密 + /// + /// + /// + internal static string Decrypt(string rs) + { + byte[] desKey = Encoding.ASCII.GetBytes("DoubanFM"); + byte[] desIV = Encoding.ASCII.GetBytes("DoubanFM"); + + using (DESCryptoServiceProvider des = new DESCryptoServiceProvider()) + try + { + //Put the input string into the byte array + byte[] inputByteArray = new byte[rs.Length / 2]; + for (int x = 0; x < rs.Length / 2; x++) + { + int i = (Convert.ToInt32(rs.Substring(x * 2, 2), 16)); + inputByteArray[x] = (byte)i; + } + + des.Key = desKey; //ASCIIEncoding.ASCII.GetBytes(sKey); + des.IV = desIV; //ASCIIEncoding.ASCII.GetBytes(sKey); + using (MemoryStream ms = new MemoryStream()) + using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write)) + { + //Flush the data through the crypto stream into the memory stream + cs.Write(inputByteArray, 0, inputByteArray.Length); + cs.FlushFinalBlock(); + + //Get the decrypted data back from the memory stream + return System.Text.Encoding.Default.GetString(ms.ToArray()); + } + } + catch + { + return rs; + } + } + } +} diff --git a/DoubanFM.Core/Json/Channel.cs b/DoubanFM.Core/Json/Channel.cs new file mode 100644 index 0000000..827cc63 --- /dev/null +++ b/DoubanFM.Core/Json/Channel.cs @@ -0,0 +1,32 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.Serialization; + +namespace DoubanFM.Core.Json +{ + /// + /// JSON格式的频道 + /// + [DataContract] + class Channel + { + /// + /// 频道ID + /// + [DataMember] + public string channel_id { get; set; } + /// + /// 频道名称 + /// + [DataMember] + public string name { get; set; } + } +} diff --git a/DoubanFM.Core/Json/ChannelInfo.cs b/DoubanFM.Core/Json/ChannelInfo.cs new file mode 100644 index 0000000..9e01d1d --- /dev/null +++ b/DoubanFM.Core/Json/ChannelInfo.cs @@ -0,0 +1,44 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Json; +using System.IO; +using System.Text.RegularExpressions; +using System.Xml; + +namespace DoubanFM.Core.Json +{ + /// + /// JSON格式的频道列表 + /// + [DataContract] + internal class ChannelInfo + { + /// + /// 私人频道 + /// + [DataMember] + public Channel[] personal { get; set; } + + /// + /// 公共频道 + /// + [DataMember(Name = "public")] + public Channel[] Public { get; set; } + + /// + /// DJ频道 + /// + [DataMember] + public Channel[] dj { get; set; } + + } +} diff --git a/DoubanFM.Core/Json/JsonHelper.cs b/DoubanFM.Core/Json/JsonHelper.cs new file mode 100644 index 0000000..ae76a68 --- /dev/null +++ b/DoubanFM.Core/Json/JsonHelper.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Serialization.Json; +using System.Text; + +namespace DoubanFM.Core.Json +{ + internal static class JsonHelper + { + public static T FromJson(string json) where T : class + { + try + { + DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T)); + using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(json))) + return (T)ser.ReadObject(stream); + } + catch + { + return null; + } + } + } +} diff --git a/DoubanFM.Core/Json/LogOnResult.cs b/DoubanFM.Core/Json/LogOnResult.cs new file mode 100644 index 0000000..1820853 --- /dev/null +++ b/DoubanFM.Core/Json/LogOnResult.cs @@ -0,0 +1,66 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Json; +using System.IO; + +namespace DoubanFM.Core.Json +{ + /// + /// JSON格式的登录结果 + /// + [DataContract] + public class LogOnResult + { + /// + /// 用户ID + /// + [DataMember] + public string user_id { get; set; } + + /// + /// 错误信息 + /// + [DataMember] + public string err { get; set; } + + /// + /// Token + /// + [DataMember] + public string token { get; set; } + + /// + /// Expire + /// + [DataMember] + public string expire { get; set; } + + /// + /// 是否发生错误 + /// + [DataMember] + public bool r { get; set; } + + /// + /// 昵称 + /// + [DataMember] + public string user_name { get; set; } + + /// + /// 电子邮箱 + /// + [DataMember] + public string email { get; set; } + + } +} \ No newline at end of file diff --git a/DoubanFM.Core/Json/PlayList.cs b/DoubanFM.Core/Json/PlayList.cs new file mode 100644 index 0000000..39fb4fc --- /dev/null +++ b/DoubanFM.Core/Json/PlayList.cs @@ -0,0 +1,40 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Json; +using System.IO; + +namespace DoubanFM.Core.Json +{ + /// + /// JSON格式的播放列表 + /// + [DataContract] + internal class PlayList + { + /// + /// 是否发生错误 + /// + [DataMember] + public bool r { get; set; } + + /// + /// 播放列表里的歌曲 + /// + [DataMember] + public List song { get; set; } + + public PlayList() + { + song = new List(); + } + } +} diff --git a/DoubanFM.Core/Json/Song.cs b/DoubanFM.Core/Json/Song.cs new file mode 100644 index 0000000..3132c4a --- /dev/null +++ b/DoubanFM.Core/Json/Song.cs @@ -0,0 +1,96 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.Serialization; + +namespace DoubanFM.Core.Json +{ + /// + /// JSON格式的歌曲 + /// + [DataContract] + class Song + { + /// + /// 专辑的豆瓣资料页面 + /// + [DataMember] + public string album { get; set; } + /// + /// 封面URL + /// + [DataMember] + public string picture { get; set; } + [DataMember] + public string ssid { get; set; } + /// + /// 表演者 + /// + [DataMember] + public string artist { get; set; } + /// + /// 音乐文件URL + /// + [DataMember] + public string url { get; set; } + /// + /// 唱片公司 + /// + [DataMember] + public string company { get; set; } + /// + /// 标题 + /// + [DataMember] + public string title { get; set; } + /// + /// 平均评分 + /// + [DataMember] + public double rating_avg { get; set; } + /// + /// 长度 + /// + [DataMember] + public double length { get; set; } + [DataMember] + public string source_url { get; set; } + /// + /// 普通音乐应该是"",广告应该是"T" + /// + [DataMember] + public string subtype { get; set; } + /// + /// 发行年 + /// + [DataMember] + public string public_time { get; set; } + /// + /// 歌曲ID + /// + [DataMember] + public string sid { get; set; } + /// + /// 专辑ID + /// + [DataMember] + public string aid { get; set; } + /// + /// 专辑 + /// + [DataMember] + public string albumtitle { get; set; } + /// + /// 当前用户喜欢与否 + /// + [DataMember] + public bool like { get; set; } + } +} diff --git a/DoubanFM.Core/Json/SongInfo.cs b/DoubanFM.Core/Json/SongInfo.cs new file mode 100644 index 0000000..59f6843 --- /dev/null +++ b/DoubanFM.Core/Json/SongInfo.cs @@ -0,0 +1,61 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.IO; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Json; +using System.Text; + +namespace DoubanFM.Core.Json +{ + /// + /// 包含歌曲的信息。(目前主要用于获取歌词) + /// + [DataContract] + internal class SongInfo + { + [DataMember(Name = "artist_region")] + public string ArtistRegion { get; set; } + + [DataMember(Name = "album_stars")] + public int AlbumStars { get; set; } + + [DataMember(Name = "album_rate")] + public double AlbumRate { get; set; } + + [DataMember(Name = "artist_name")] + public string ArtistName { get; set; } + + //[DataMember(Name = "photos")] + //public SongPhoto Photos { get; set; } + + [DataMember(Name = "lyric")] + public string Lyric { get; set; } + + //[DataMember(Name = "albums")] + //public SongAlbum[] Albums { get; set; } + + [DataMember(Name = "artist_birth")] + public string ArtistBirth { get; set; } + + [DataMember(Name = "subject_id")] + public string SubjectID { get; set; } + + [DataMember(Name = "album_intro")] + public string AlbumIntro { get; set; } + + [DataMember(Name = "artist_intro")] + public string ArtistIntro { get; set; } + + [DataMember(Name = "artist_id")] + public int ArtistID { get; set; } + + [DataMember(Name = "artist_gene")] + public string ArtistGene { get; set; } + + } +} \ No newline at end of file diff --git a/DoubanFM.Core/Json/UserInfo.cs b/DoubanFM.Core/Json/UserInfo.cs new file mode 100644 index 0000000..36b1777 --- /dev/null +++ b/DoubanFM.Core/Json/UserInfo.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Json; +using System.Text; + +namespace DoubanFM.Core.Json +{ + /// + /// JSON格式的用户信息 + /// + [DataContract] + internal class UserInfo + { + /// + /// 用户ID + /// + [DataMember] + public string user_id { get; set; } + + /// + /// 错误信息 + /// + [DataMember] + public string err { get; set; } + + /// + /// 是否发生错误 + /// + [DataMember] + public bool r { get; set; } + + /// + /// 昵称 + /// + [DataMember] + public string name { get; set; } + + /// + /// 累积收听歌曲数量 + /// + [DataMember] + public int played_num { get; set; } + + /// + /// 加红心歌曲数量 + /// + [DataMember] + public int liked_num { get; set; } + + /// + /// 不再播放歌曲数量 + /// + [DataMember] + public int banned_num { get; set; } + + /// + /// Pro服务到期时间 + /// + [DataMember] + public string pro_expire_date { get; set; } + + /// + /// Pro服务状态 + /// + [DataMember] + public string pro_status { get; set; } + + /// + /// 用户头像 + /// + [DataMember] + public string icon { get; set; } + } +} diff --git a/DoubanFM.Core/Lyrics/Lyrics.cs b/DoubanFM.Core/Lyrics/Lyrics.cs new file mode 100644 index 0000000..d285b73 --- /dev/null +++ b/DoubanFM.Core/Lyrics/Lyrics.cs @@ -0,0 +1,159 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * Reference : http://equinox1993.blog.163.com/blog/static/32205137201031141228418/ + * */ + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text.RegularExpressions; + +namespace DoubanFM.Core +{ + /// + /// 表示一个LRC格式的歌词 + /// + public class Lyrics + { + #region values + + /// + /// 获取LRC歌词代码 + /// + public string LrcCode { get; private set; } + + /// + /// 获取原始字典 + /// + public Dictionary Dictionary { get; private set; } + + /// + /// 时间、歌词字典 + /// + public Dictionary TimeAndLyrics { get; set; } + + /// + /// 返回歌词的标题 + /// + public string Title { get; private set; } + + /// + /// 返回歌词的专辑名称 + /// + public string Album { get; private set; } + + /// + /// 返回歌词的表演者 + /// + public string Artist { get; private set; } + + /// + /// 返回歌词的制作者 + /// + public string LyricsMaker { get; private set; } + + /// + /// 获取LRC歌词的偏移 + /// + public TimeSpan Offset { get; private set; } + + #endregion + + #region build + + /// + /// 通过指定的Lrc代码初始化LyricParser实例 + /// + /// Lrc代码 + public Lyrics(string code) + { + try + { + LrcCode = code; + LrcCodeParse(); + DictionaryParse(); + } + catch (Exception ex) + { + Debug.WriteLine(ex.ToString()); + throw; + } + } + + #endregion + + #region protected functions + + /// + /// 第一次处理,生成原始字典 + /// + protected void LrcCodeParse() + { + Dictionary = new Dictionary(); + string[] lines = LrcCode.Replace(@"\'", "'").Split(new char[2] {'\r', '\n'}); + int i; + for (i = 0; i < lines.Length; i++) + { + if (!string.IsNullOrEmpty(lines[i])) + { + var mc = Regex.Matches(lines[i], + @"(?'titles'\[(\d+:\d+(\.\d+)?|(ti|ar|al|by|offset):.*?)\])+(?'content'.+?(?=\[(\d+:\d+(\.\d+)?|(ti|ar|al|by|offset):.*?)\])|.*$)", + RegexOptions.None); + foreach (Match ma in mc) + { + if (ma.Success) + { + string content = ma.Groups["content"].Value; + foreach (Capture title in ma.Groups["titles"].Captures) + Dictionary[title.Value] = content; //不要用Add方法,有可能有重复项 + } + } + } + } + } + + /// + /// 第二次处理,生成时间、歌词字典,找到歌词的作者等属性 + /// + protected void DictionaryParse() + { + TimeAndLyrics = new Dictionary(); + foreach (var keyvalue in Dictionary) + { + { + //分析时间 + Match mc = Regex.Match(keyvalue.Key, @"\[(?'minutes'\d+):(?'seconds'\d+(\.\d+)?)\]", + RegexOptions.None); + if (mc.Success) + { + int minutes = int.Parse(mc.Groups["minutes"].Value); + double seconds = double.Parse(mc.Groups["seconds"].Value); + TimeSpan key = new TimeSpan(0, 0, minutes, (int) Math.Floor(seconds), + (int) ((seconds - Math.Floor(seconds))*1000)); + string value = keyvalue.Value; + TimeAndLyrics[key] = value; + } + } + { + //分析歌词的附带属性 + Match mc = Regex.Match(keyvalue.Key, @"\[(?'title'.+?):(?'content'.*)\]", RegexOptions.None); + if (mc.Success) + { + string title = mc.Groups["title"].Value.ToLower(); + string content = mc.Groups["content"].Value; + if (title == "ti") Title = content; + if (title == "ar") Artist = content; + if (title == "al") Album = content; + if (title == "by") LyricsMaker = content; + if (title == "offset") Offset = new TimeSpan(10000*int.Parse(content)); + } + } + } + } + + #endregion + + } +} \ No newline at end of file diff --git a/DoubanFM.Core/Lyrics/LyricsHelper.cs b/DoubanFM.Core/Lyrics/LyricsHelper.cs new file mode 100644 index 0000000..f34b78b --- /dev/null +++ b/DoubanFM.Core/Lyrics/LyricsHelper.cs @@ -0,0 +1,56 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Diagnostics; + +namespace DoubanFM.Core +{ + /// + /// 获取歌词 + /// + public class LyricsHelper + { + /// + /// 获取歌词 + /// + /// 歌曲 + /// 歌词 + public static Lyrics GetLyrics(Song song) + { + //优先获取来自豆瓣的歌词。 + var lyrics = GetDoubanLyrics(song); + return lyrics ?? TTPlayerLyrics.GetLyrics(song.Artist, song.Title); + } + + /// + /// 从豆瓣获取歌词 + /// + /// 歌曲 + /// 歌词 + protected static Lyrics GetDoubanLyrics(Song song) + { + Parameters parameters = new Parameters(); + parameters["song_id"] = song.SongId; + var url = ConnectionBase.ConstructUrlWithParameters("http://music.douban.com/api/song/info", parameters); + var content = new ConnectionBase().Get(url); + if (string.IsNullOrEmpty(content)) return null; + + var songInfo = Json.JsonHelper.FromJson(content); + if (songInfo == null || string.IsNullOrEmpty(songInfo.Lyric)) return null; + + try + { + return new Lyrics(songInfo.Lyric); + } + catch (Exception ex) + { + Debug.WriteLine(ex.ToString()); + return null; + } + } + } +} diff --git a/DoubanFM.Core/Lyrics/LyricsItem.cs b/DoubanFM.Core/Lyrics/LyricsItem.cs new file mode 100644 index 0000000..dd7a6a6 --- /dev/null +++ b/DoubanFM.Core/Lyrics/LyricsItem.cs @@ -0,0 +1,37 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Serialization; + +namespace DoubanFM.Core +{ + /// + /// 表示歌词搜索结果中的一个歌词文件 + /// + [XmlTypeAttribute("lrc")] + public class LyricsItem + { + /// + /// ID + /// + [XmlAttribute("id")] + public int Id { get; set; } + /// + /// 艺术家 + /// + [XmlAttribute("artist")] + public string Artist { get; set; } + /// + /// 曲目名称 + /// + [XmlAttribute("title")] + public string Title { get; set; } + } +} diff --git a/DoubanFM.Core/Lyrics/LyricsResult.cs b/DoubanFM.Core/Lyrics/LyricsResult.cs new file mode 100644 index 0000000..63bef07 --- /dev/null +++ b/DoubanFM.Core/Lyrics/LyricsResult.cs @@ -0,0 +1,22 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Serialization; + +namespace DoubanFM.Core +{ + /// + /// 表示歌词搜索结果 + /// + [XmlRootAttribute("result")] + public class LyricsResult : List + { + } +} diff --git a/DoubanFM.Core/Lyrics/TTPlayerLyrics.cs b/DoubanFM.Core/Lyrics/TTPlayerLyrics.cs new file mode 100644 index 0000000..bf60685 --- /dev/null +++ b/DoubanFM.Core/Lyrics/TTPlayerLyrics.cs @@ -0,0 +1,223 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * Reference : http://www.iscripts.org/forum.php?mod=viewthread&action=printable&tid=85 + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.Xml.Serialization; + +namespace DoubanFM.Core +{ + /// + /// 用于搜索歌词的工具,使用千千静听的歌词服务器 + /// + internal static class TTPlayerLyrics + { + /// + /// 歌词服务器列表 + /// + private static readonly string[] servers = new string[] { "ttlrcct.qianqian.com", "ttlrcct2.qianqian.com" }; + + /// + /// 获取歌词 + /// + /// 表演者 + /// 标题 + public static Lyrics GetLyrics(string artist, string title) + { + if (string.IsNullOrEmpty(artist) && string.IsNullOrEmpty(title)) return null; + if (title.ToLower().Contains("instrumental")) return null; + + //获取所有可能的歌词 + Parameters parameters = new Parameters(); + parameters["Artist"] = Encode(artist); + parameters["Title"] = Encode(title); + parameters["Flag"] = "2"; + + foreach (var server in servers) + { + string url = ConnectionBase.ConstructUrlWithParameters("http://" + server +"/dll/lyricsvr.dll?sh", parameters); + string file = new ConnectionBase().Get(url); + + //分析返回的XML文件 + LyricsResult result = null; + try + { + using (MemoryStream stream = new MemoryStream()) + using (StreamWriter writer = new StreamWriter(stream)) + { + writer.Write(file); + writer.Flush(); + XmlSerializer serializer = new XmlSerializer(typeof(LyricsResult)); + stream.Position = 0; + result = (LyricsResult)serializer.Deserialize(stream); + } + } + catch { } + if (result == null || result.Count == 0) continue; + + //选出最合适的歌词文件 + LyricsItem selected = result[0]; + double dist = double.MaxValue; + string lArtist = artist.ToLower(); + string lTitle = title.ToLower(); + foreach (var item in result) + { + string iArtist = item.Artist.ToLower(); + string iTitle = item.Title.ToLower(); + if (lArtist == iArtist && lTitle == iTitle) + { + selected = item; + break; + } + else if (lArtist.Length < 100 && lTitle.Length < 100 && iArtist.Length < 100 && iTitle.Length < 100) + { + int dist1 = Distance(lArtist, iArtist); + int dist2 = Distance(lTitle, iTitle); + double temp = ((double)(dist1 + dist2)) / (lArtist.Length + lTitle.Length); + if (temp < dist) + { + dist = temp; + selected = item; + } + } + } + + //下载歌词文件 + Parameters parameters2 = new Parameters(); + parameters2["Id"] = selected.Id.ToString(); + parameters2["Code"] = VerifyCode(selected.Artist, selected.Title, selected.Id); + string url2 = ConnectionBase.ConstructUrlWithParameters("http://" + server + "/dll/lyricsvr.dll?dl", parameters2); + string file2 = new ConnectionBase().Get(url2); + + //生成Lyrics的实例 + if (string.IsNullOrEmpty(file2)) continue; + try + { + return new Lyrics(file2); + } + catch + { + continue; + } + } + + return null; + } + + /// + /// 对数据编码 + /// + static string Encode(string data) + { + if (data == null) return ""; + var index = data.IndexOfAny(new char[] { '(', '[', '{', '(' }); + if (index != -1) + { + data = data.Substring(0, index); + } + data = new string(data.Where(ch => char.IsLetterOrDigit(ch)).ToArray()); + var bytes = Encoding.Unicode.GetBytes(data); + StringBuilder sb = new StringBuilder(); + foreach (var b in bytes) + { + sb.Append(b.ToString("X2")); + } + return sb.ToString(); + } + + /// + /// 生成校验码 + /// + static string VerifyCode(string artist, string title, int lrcId) + { + byte[] bytes = Encoding.UTF8.GetBytes(artist + title); + int[] song = new int[bytes.Length]; + for (int i = 0; i < bytes.Length; i++) + song[i] = bytes[i] & 0xff; + int intVal1 = 0, intVal2 = 0, intVal3 = 0; + intVal1 = (lrcId & 0xFF00) >> 8; + if ((lrcId & 0xFF0000) == 0) + { + intVal3 = 0xFF & ~intVal1; + } + else + { + intVal3 = 0xFF & ((lrcId & 0x00FF0000) >> 16); + } + intVal3 = intVal3 | ((0xFF & lrcId) << 8); + intVal3 = intVal3 << 8; + intVal3 = intVal3 | (0xFF & intVal1); + intVal3 = intVal3 << 8; + if ((lrcId & 0xFF000000) == 0) + { + intVal3 = intVal3 | (0xFF & (~lrcId)); + } + else + { + intVal3 = intVal3 | (0xFF & (lrcId >> 24)); + } + int uBound = bytes.Length - 1; + while (uBound >= 0) + { + int c = song[uBound]; + if (c >= 0x80) + c = c - 0x100; + intVal1 = c + intVal2; + intVal2 = intVal2 << (uBound % 2 + 4); + intVal2 = intVal1 + intVal2; + uBound -= 1; + } + uBound = 0; + intVal1 = 0; + while (uBound <= bytes.Length - 1) + { + int c = song[uBound]; + if (c >= 128) + c = c - 256; + int intVal4 = c + intVal1; + intVal1 = intVal1 << (uBound % 2 + 3); + intVal1 = intVal1 + intVal4; + uBound += 1; + } + int intVal5 = intVal2 ^ intVal3; + intVal5 = intVal5 + (intVal1 | lrcId); + intVal5 = intVal5 * (intVal1 | intVal3); + intVal5 = intVal5 * (intVal2 ^ lrcId); + return intVal5.ToString(); + } + + /// + /// Levenshtein Distance算法,计算两个字符串之间的差异 + /// + static int Distance(string a, string b) + { + if (string.IsNullOrEmpty(a)) return b == null ? 0 : b.Length; + if (string.IsNullOrEmpty(b)) return a.Length; + int[][] d = new int[a.Length + 1][]; + for (int i = 0; i < d.Length; ++i) + d[i] = new int[b.Length + 1]; + + for (int i = 0; i <= a.Length; ++i) + d[i][0] = i; + for (int j = 0; j <= b.Length; ++j) + d[0][j] = j; + for (int i = 1; i <= a.Length; ++i) + for (int j = 1; j <= b.Length; ++j) + { + d[i][j] = int.MaxValue; + if (d[i - 1][j] + 1 < d[i][j]) d[i][j] = d[i - 1][j] + 1; + if (d[i][j - 1] + 1 < d[i][j]) d[i][j] = d[i][j - 1] + 1; + if (d[i - 1][j - 1] + (a[i - 1] == b[j - 1] ? 0 : 1) < d[i][j]) + d[i][j] = d[i - 1][j - 1] + (a[i - 1] == b[j - 1] ? 0 : 1); + } + return d[a.Length][b.Length]; + } + } +} diff --git a/DoubanFM.Core/Player/Channel.cs b/DoubanFM.Core/Player/Channel.cs new file mode 100644 index 0000000..f16aaf5 --- /dev/null +++ b/DoubanFM.Core/Player/Channel.cs @@ -0,0 +1,208 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace DoubanFM.Core +{ + /// + /// 频道 + /// + [Serializable] + public class Channel : ICloneable, IEquatable + { + /// + /// 频道ID + /// + public string Id { get; private set; } + /// + /// 频道名称 + /// + public string Name { get; private set; } + /// + /// 上下文 + /// + public string Context { get; private set; } + + /// + /// 是否是有效的频道 + /// + public bool IsEffective { get { return !string.IsNullOrEmpty(Id) && !string.IsNullOrEmpty(Name); } } + + /// + /// 是否是DJ频道 + /// + public bool IsDj + { + get + { + int x = 0; + if (!int.TryParse(Id, out x)) + { + return false; + } + return x >= 1000000; + } + } + /// + /// 是否是私人频道 + /// + public bool IsPersonal { get { return Id == PersonalId || Id == RedHeartId; } } + /// + /// 是否是红心频道 + /// + public bool IsRedHeart { get { return Id == RedHeartId; } } + /// + /// 是否是公共频道 + /// + public bool IsPublic { get { return !IsDj && !IsPersonal; } } + /// + /// 是否是特殊模式 + /// + public bool IsSpecial { get { return !string.IsNullOrEmpty(Context); } } + + internal Channel(Json.Channel channel) + { + Id = channel.channel_id; + Name = channel.name; + } + + internal Channel(string id, string name, string context = null) + { + Id = id; + Name = name; + Context = context; + } + + /// + /// 由命令行参数构造Channel + /// + /// The args. + /// + public static Channel FromCommandLineArgs(List args) + { + if (args.Contains("-channel")) + { + int index = args.IndexOf("-channel"); + if (index != -1) + try + { + string id = Encoding.Unicode.GetString(Convert.FromBase64String(args.ElementAt(index + 1))); + string name = Encoding.Unicode.GetString(Convert.FromBase64String(args.ElementAt(index + 2))); + string context = Encoding.Unicode.GetString(Convert.FromBase64String(args.ElementAt(index + 3))); + return new Channel(id, name, context); + } + catch { } + } + return null; + } + + /// + /// 由命令行参数构造Channel(简单版本,不适用于复杂的命令行) + /// + /// 命令行 + /// + public static Channel FromCommandLineArgs(string commandLine) + { + List args = new List(); + MatchCollection mc = Regex.Matches(commandLine, @"""(.*?)""|([^""\s]+)"); + foreach (Match ma in mc) + { + for (int i = 1; i < ma.Groups.Count; ++i) + { + if (ma.Groups[i].Success) + { + args.Add(ma.Groups[i].Value); + } + } + } + return FromCommandLineArgs(args); + } + + /// + /// 转换为命令行参数 + /// + /// + public string ToCommandLineArgs() + { + StringBuilder sb = new StringBuilder(); + sb.Append("-channel "); + + sb.Append("\""); + sb.Append(Convert.ToBase64String(Encoding.Unicode.GetBytes(Id))); + sb.Append("\" "); + + sb.Append("\""); + sb.Append(Convert.ToBase64String(Encoding.Unicode.GetBytes(Name))); + sb.Append("\" "); + + sb.Append("\""); + sb.Append(Convert.ToBase64String(Encoding.Unicode.GetBytes(Context == null ? "" : Context))); + sb.Append("\" "); + + return sb.ToString(); + } + + /// + /// 私人兆赫的频道ID + /// + public const string PersonalId = "0"; + /// + /// 红心兆赫的频道ID + /// + public const string RedHeartId = "-3"; + + /// + /// 创建作为当前实例副本的新对象。 + /// + /// + /// 作为此实例副本的新对象。 + /// + public object Clone() + { + return this.MemberwiseClone(); + } + + public override string ToString() + { + return Name; + } + public override bool Equals(object obj) + { + return this.Equals(obj as Channel); + } + public override int GetHashCode() + { + return Id.GetHashCode() ^ Name.GetHashCode() ^ (string.IsNullOrEmpty(Context) ? 0 : Context.GetHashCode()); + } + + public bool Equals(Channel other) + { + if (Object.ReferenceEquals(other, null)) + return false; + if (Object.ReferenceEquals(this, other)) + return true; + return Id == other.Id && ((string.IsNullOrEmpty(Context) && string.IsNullOrEmpty(other.Context)) || Context == other.Context); + } + + public static bool operator ==(Channel lhs, Channel rhs) + { + if (Object.ReferenceEquals(lhs, null)) + if (Object.ReferenceEquals(rhs, null)) + return true; + else return false; + return lhs.Equals(rhs); + } + public static bool operator !=(Channel lhs, Channel rhs) + { + return !(lhs == rhs); + } + } +} \ No newline at end of file diff --git a/DoubanFM.Core/Player/ChannelInfo.cs b/DoubanFM.Core/Player/ChannelInfo.cs new file mode 100644 index 0000000..91406f4 --- /dev/null +++ b/DoubanFM.Core/Player/ChannelInfo.cs @@ -0,0 +1,81 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DoubanFM.Core +{ + /// + /// 频道列表 + /// + public class ChannelInfo + { + /// + /// 私人频道 + /// + public IEnumerable Personal { get; private set; } + /// + /// 公共频道 + /// + public IEnumerable Public { get; private set; } + /// + /// DJ频道 + /// + public IEnumerable Dj { get; private set; } + + /// + /// 是否是有效的频道列表 + /// + public bool IsEffective { get { return Personal != null && Public != null && Public.Count() > 0 && Dj != null; } } + + internal ChannelInfo(Json.ChannelInfo ci) + { + if (ci == null) return; + List list1 = new List(); + if (ci.personal != null) + { + foreach (var channel in ci.personal) + { + Channel ch = new Channel(channel); + if (ch.IsEffective) + { + list1.Add(ch); + } + } + } + Personal = list1; + List list2 = new List(); + if (ci.Public != null) + { + foreach (var channel in ci.Public) + { + Channel ch = new Channel(channel); + if (ch.IsEffective) + { + list2.Add(ch); + } + } + } + Public = list2; + List list3 = new List(); + if (ci.dj != null) + { + foreach (var channel in ci.dj) + { + Channel ch = new Channel(channel); + if (ch.IsEffective) + { + list3.Add(ch); + } + } + } + Dj = list3; + } + } +} diff --git a/DoubanFM.Core/Player/PlayList.cs b/DoubanFM.Core/Player/PlayList.cs new file mode 100644 index 0000000..56a4954 --- /dev/null +++ b/DoubanFM.Core/Player/PlayList.cs @@ -0,0 +1,121 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; + +namespace DoubanFM.Core +{ + /// + /// 播放列表 + /// + public class PlayList : List + { + /// + /// 当获取播放列表失败时发生。 + /// + internal static event EventHandler GetPlayListFailed; + + static Random random = new Random(); + static byte[] bytes = new byte[8]; + + private static void RaiseGetPlayListFailedEvent(string json) + { + if (GetPlayListFailed != null) + GetPlayListFailed(null, new PlayListEventArgs(json)); + } + + internal PlayList(Json.PlayList pl) + { + if (pl != null &&pl.song != null) + foreach (var song in pl.song) + { + this.Add(new Song(song)); + } + } + + /// + /// 获取播放列表 + /// + /// 播放器状态 + /// 操作类型 + /// + /// 播放列表 + /// + internal static PlayList GetPlayList(Player.PlayerState playerState, string operationType) + { + //构造链接 + Parameters parameters = new Parameters(); + parameters["app_name"] = "radio_desktop_win"; + parameters["version"] = "100"; + parameters["user_id"] = playerState.CurrentUser.UserID; + parameters["token"] = playerState.CurrentUser.Token; + parameters["expire"] = playerState.CurrentUser.Expire; + parameters["from"] = "mainsite"; + parameters["context"] = playerState.CurrentChannel.Context; + parameters["sid"] = playerState.CurrentSong != null ? playerState.CurrentSong.SongId : null; + parameters["channel"] = playerState.CurrentChannel.Id; + parameters["type"] = operationType; + random.NextBytes(bytes); + parameters["r"] = (BitConverter.ToUInt64(bytes, 0) % 0xFFFFFFFFFF).ToString("x10"); + + if (playerState.CurrentUser.IsPro) + { + string kbps = null; + switch (playerState.CurrentUser.ProRate) + { + case ProRate.Kbps64: + kbps = "64"; + break; + case ProRate.Kbps128: + kbps = "128"; + break; + case ProRate.Kbps192: + kbps = "192"; + break; + default: + break; + } + parameters["kbps"] = kbps; + } + + string url = ConnectionBase.ConstructUrlWithParameters("http://www.douban.com/j/app/radio/people", parameters); + + //获取列表 + string json = new ConnectionBase().Get(url, @"application/json, text/javascript, */*; q=0.01", @"http://douban.fm"); + var jsonPlayList = Json.JsonHelper.FromJson(json); + if (jsonPlayList != null && jsonPlayList.r) + RaiseGetPlayListFailedEvent(json); + PlayList pl = new PlayList(jsonPlayList); + + //将小图更换为大图 + foreach (var s in pl) + { + s.Picture = s.Picture.Replace("/mpic/", "/lpic/").Replace("//otho.", "//img3."); + } + + //去广告 + pl.RemoveAll(s => s.IsAd); + + return pl; + } + + /// + /// 播放列表的事件参数 + /// + public class PlayListEventArgs : EventArgs + { + /// + /// 消息 + /// + public string Message { get; private set; } + internal PlayListEventArgs(string message) + { + Message = message; + } + } + } +} diff --git a/DoubanFM.Core/Player/Player.cs b/DoubanFM.Core/Player/Player.cs new file mode 100644 index 0000000..f9c1f84 --- /dev/null +++ b/DoubanFM.Core/Player/Player.cs @@ -0,0 +1,931 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.IO; +using System.Threading; +using System.Windows; +using System.Diagnostics; +using System.Configuration; + +namespace DoubanFM.Core +{ + /// + /// 播放器核心 + /// + public class Player : DependencyObject + { + #region 依赖项属性 + + public static readonly DependencyProperty IsInitializedProperty = DependencyProperty.Register("IsInitialized", typeof(bool), typeof(Player)); + public static readonly DependencyProperty CurrentChannelProperty = DependencyProperty.Register("CurrentChannel", typeof(Channel), typeof(Player)); + public static readonly DependencyProperty CurrentSongProperty = DependencyProperty.Register("CurrentSong", typeof(Song), typeof(Player), new PropertyMetadata(new PropertyChangedCallback((d, e) => + { + (d as Player).RaiseCurrentSongChangedEvent(); + }))); + public static readonly DependencyProperty IsLikedProperty = DependencyProperty.Register("IsLiked", typeof(bool), typeof(Player), + new PropertyMetadata(new PropertyChangedCallback((o, e) => + { + Player player = (Player)o; + if (player.CurrentSong == null) return; + player.RaiseIsLikedChangedEvent(); + if ((bool)e.NewValue == player.CurrentSong.Like) return; + if (player.CurrentSong.Like == false) player.Like(); + else player.Unlike(); + }))); + public static readonly DependencyProperty IsLikedEnabledProperty = DependencyProperty.Register("IsLikedEnabled", typeof(bool), typeof(Player), new PropertyMetadata(true)); + public static readonly DependencyProperty IsNeverEnabledProperty = DependencyProperty.Register("IsNeverEnabled", typeof(bool), typeof(Player)); + public static readonly DependencyProperty IsPlayingProperty = DependencyProperty.Register("IsPlaying", typeof(bool), typeof(Player), + new PropertyMetadata(true, new PropertyChangedCallback((o, e) => + { + Player player = (Player)o; + if ((bool)e.NewValue == true) player.Play(); + else player.Pause(); + player.RaiseIsPlayingChangedEvent(); + }))); + public static readonly DependencyProperty SettingsProperty = DependencyProperty.Register("Settings", typeof(Settings), typeof(Player)); + + #endregion + + #region 属性 + + /// + /// 频道列表 + /// + public ChannelInfo ChannelInfo { get; private set; } + /// + /// 当前频道 + /// + public Channel CurrentChannel + { + get { return (Channel)GetValue(CurrentChannelProperty); } + set + { + if (CurrentChannel != value) + { + if (!IsInitialized) return; + if (value == null) + throw new Exception("频道不能设为空"); + if (value.IsPersonal && !value.IsSpecial && !UserAssistant.IsLoggedOn) return; //没登录时不能使用私人频道 + if (!value.IsSpecial && !ChannelInfo.Personal.Contains(value) && !ChannelInfo.Public.Contains(value) && !ChannelInfo.Dj.Contains(value)) return; //除特殊频道外,无法播放频道列表中不存在的频道 + RaiseStopedEvent(); + Channel lastChannel = CurrentChannel; + CurrentSong = null; + SetValue(CurrentChannelProperty, value); + Settings.LastChannel = CurrentChannel; + NewPlayList(); + RaiseCurrentChannelChangedEvent(); + } + } + } + /// + /// 当前歌曲 + /// + public Song CurrentSong + { + get { return (Song)GetValue(CurrentSongProperty); } + protected set { SetValue(CurrentSongProperty, value); } + } + /// + /// 设置 + /// + public Settings Settings + { + get { return (Settings)GetValue(SettingsProperty); } + set { SetValue(SettingsProperty, value); } + } + /// + /// 是否已初始化 + /// + public bool IsInitialized + { + get { return (bool)GetValue(IsInitializedProperty); } + private set + { + if (value == false) return; + if (IsInitialized == false) + { + SetValue(IsInitializedProperty, true); + RaiseInitializedEvent(); + } + } + } + /// + /// 是否正在播放 + /// + public bool IsPlaying + { + get { return (bool)GetValue(IsPlayingProperty); } + set { SetValue(IsPlayingProperty, value); } + } + /// + /// 是否喜欢这首歌 + /// + public bool IsLiked + { + get { return (bool)GetValue(IsLikedProperty); } + set + { + if (!IsLikedEnabled) return; + SetValue(IsLikedProperty, value); + } + } + /// + /// 获取一个值,该值指示红心是否启用 + /// + public bool IsLikedEnabled + { + get { return (bool)GetValue(IsLikedEnabledProperty); } + private set + { + if (IsLikedEnabled != value) + { + SetValue(IsLikedEnabledProperty, value); + RaiseIsLikedEnabledChangedEvent(); + } + } + } + /// + /// 获取一个值,该值指示垃圾桶是否启用 + /// + public bool IsNeverEnabled + { + get { return (bool)GetValue(IsNeverEnabledProperty); } + private set + { + if (IsNeverEnabled != value) + { + SetValue(IsNeverEnabledProperty, value); + RaiseIsNeverEnabledChangedEvent(); + } + } + } + /// + /// 处理登录、注销等 + /// + public UserAssistant UserAssistant { get; private set; } + /// + /// 频道搜索 + /// + public ChannelSearch ChannelSearch { get; private set; } + + #endregion + + #region 成员变量 + + /// + /// 待播放音乐的列表 + /// + private Queue _playListSongs = new Queue(); + /// + /// 上次暂停的时间 + /// + private DateTime _pauseTime = DateTime.Now; + /// + /// 防止同时进行多个任务的锁 + /// + private object workLock = new object(); + /// + /// 是否正有一个“下一首”任务正在执行 + /// + private bool _skipping; + /// + /// 是否正有一个“不再播放”任务正在执行 + /// + private bool _neverring; + + #endregion + + #region 事件 + + /// + /// 当当前频道改变时发生。 + /// + public event EventHandler CurrentChannelChanged; + private void RaiseCurrentChannelChangedEvent() + { + if (CurrentChannelChanged != null) + CurrentChannelChanged(this, EventArgs.Empty); + } + /// + /// 当当前歌曲改变时发生。 + /// + public event EventHandler CurrentSongChanged; + private void RaiseCurrentSongChangedEvent() + { + if (CurrentSongChanged != null) + CurrentSongChanged(this, EventArgs.Empty); + } + /// + /// 当初始化完成时发生。 + /// + public event EventHandler Initialized; + private void RaiseInitializedEvent() + { + if (Initialized != null) + Initialized(this, EventArgs.Empty); + } + /// + /// 当音乐继续时发生。 + /// + public event EventHandler Played; + private void RaisePlayedEvent() + { + if (Played != null) + Played(this, EventArgs.Empty); + } + /// + /// 当音乐暂停时发生。 + /// + public event EventHandler Paused; + private void RaisePausedEvent() + { + if (Paused != null) + Paused(this, EventArgs.Empty); + } + /// + /// 当音乐停止时发生。 + /// + public event EventHandler Stoped; + private void RaiseStopedEvent() + { + if (Stoped != null) + Stoped(this, EventArgs.Empty); + } + /// + /// 当IsLiked改变时发生。 + /// + public event EventHandler IsLikedChanged; + private void RaiseIsLikedChangedEvent() + { + if (IsLikedChanged != null) + IsLikedChanged(this, EventArgs.Empty); + } + /// + /// 当IsLikedEnabled改变时发生。 + /// + public event EventHandler IsLikedEnabledChanged; + private void RaiseIsLikedEnabledChangedEvent() + { + if (IsLikedEnabledChanged != null) + IsLikedEnabledChanged(this, EventArgs.Empty); + } + /// + /// 当IsNeverEnabled改变时发生。 + /// + public event EventHandler IsNeverEnabledChanged; + private void RaiseIsNeverEnabledChangedEvent() + { + if (IsNeverEnabledChanged != null) + IsNeverEnabledChanged(this, EventArgs.Empty); + } + /// + /// 当IsPlaying改变时发生。 + /// + public event EventHandler IsPlayingChanged; + private void RaiseIsPlayingChangedEvent() + { + if (IsPlayingChanged != null) + IsPlayingChanged(this, EventArgs.Empty); + } + /// + /// 当获取播放列表失败时发生。 + /// + public event EventHandler GetPlayListFailed; + private void RaiseGetPlayListFailedEvent(PlayList.PlayListEventArgs e) + { + if (GetPlayListFailed != null) + GetPlayListFailed(this, e); + } + /// + /// 当一首歌自然播放完成时向服务器发送添加播放记录的消息失败时发生。 + /// + public event EventHandler FinishedPlayingReportFailed; + private void RaiseFinishedPlayingReportFailedEvent(ErrorEventArgs e) + { + if (FinishedPlayingReportFailed != null) + { + FinishedPlayingReportFailed(this, e); + } + } + + /// + /// 当用户的播放记录发生改变时发生。 + /// + public event EventHandler PlayRecordChanged; + private void RaisePlayRecordChangedEvent() + { + if (PlayRecordChanged != null) + { + PlayRecordChanged(this, EventArgs.Empty); + } + } + + /// + /// 当用户的登录状态过期时发生。 + /// + public event EventHandler UserExpired; + private void RaiseUserExpiredEvent() + { + if (UserExpired != null) + { + UserExpired(this, EventArgs.Empty); + } + } + + #endregion + + #region 构造及初始化 + + public Player() + : base() + { + LoadSettings(); + UserAssistant = new UserAssistant(); + UserAssistant.Settings = Settings; + ChannelSearch = new ChannelSearch(Settings); + DownloadSearch.Settings = Settings; + + //加红心功能始终启用 + IsLikedEnabled = true; + + //歌曲改变时更新红心状态 + CurrentSongChanged += new EventHandler((o, e) => + { + if (CurrentSong != null) + { + IsLiked = CurrentSong.Like; + } + }); + + UserAssistant.CurrentStateChanged += (o, e) => + { + //更新IsNeverEnabled + IsNeverEnabled = UserAssistant.CurrentState == UserAssistant.State.LoggedOn || UserAssistant.CurrentState == UserAssistant.State.LoggingOff; + switch ((UserAssistant.State) e.NewValue) + { + case UserAssistant.State.LoggedOn: + RaisePlayRecordChangedEvent(); + break; + case UserAssistant.State.LoggedOff: + if (CurrentChannel != null && CurrentChannel.IsPersonal && !CurrentChannel.IsSpecial) + CurrentChannel = ChannelInfo.Public.First(); + break; + } + }; + + //获取播放列表失败后引发事件 + PlayList.GetPlayListFailed += (o, e) => Dispatcher.Invoke(new Action(() => RaiseGetPlayListFailedEvent(e))); + } + /// + /// 播放器初始化 + /// + public void Initialize() + { + if (IsInitialized) return; + Debug.WriteLine(DateTime.Now + " 播放器核心初始化中"); + //bool lastTimeLoggedOn = Settings.LastTimeLoggedOn; + ThreadPool.QueueUserWorkItem(new WaitCallback((state) => + { + ////如果用户上次退出软件时处于未登录状态,则启动时不更新登录状态 + //if (lastTimeLoggedOn) + //{ + // string file; + // while (true) + // { + // Debug.WriteLine(DateTime.Now + " 刷新豆瓣FM主页……"); + // file = new ConnectionBase().Get("http://douban.fm/"); + // Debug.WriteLine(DateTime.Now + " 刷新完成"); + // if (!string.IsNullOrEmpty(file)) + // { + // break; + // } + // TakeABreak(); + // } + + // //更新用户的登录状态 + // UserAssistant.Update(file); + //} + + //检查用户登录状态是否已过期。 + bool expired = !string.IsNullOrEmpty(UserAssistant.Settings.User.Token); + UserAssistant.Initialize(); + expired = expired && string.IsNullOrEmpty(UserAssistant.Settings.User.Token); + + var channelInfo = GetChannelInfo(); + + Dispatcher.Invoke(new Action(() => + { + /** + 当上次退出时是登录状态,但之后在浏览器里注销后,再打开软件会显示未登录, + 但Cookie还在,如果不清除Cookie,第一次登录会失败,清除后第一次登录也能成功 + * */ + //if (UserAssistant.CurrentState != Core.UserAssistant.State.LoggedOn) + // UserAssistant.LogOff(); + ChannelInfo = channelInfo; + RaisePlayRecordChangedEvent(); + IsInitialized = true; + Debug.WriteLine(DateTime.Now + " 播放器核心初始化完成"); + + if (expired) + { + RaiseUserExpiredEvent(); + } + + //选择一个频道 + ChooseChannelAtStartup(); + })); + })); + } + + /// + /// 根据情况从本地或服务器获取频道列表。 + /// + /// 频道列表 + private static ChannelInfo GetChannelInfo() + { + var localPath = Path.Combine(ConnectionBase.DataFolder, "channelinfo"); + ChannelInfo localChannelInfo = null; + + //尝试获取本地频道列表 + try + { + if (File.Exists(localPath)) + { + var localChannelInfoTime = File.GetLastWriteTime(localPath); + var content = File.ReadAllText(localPath); + var channelInfo = new ChannelInfo(Json.JsonHelper.FromJson(content)); + if (channelInfo.IsEffective) + { + localChannelInfo = channelInfo; + } + + //满足条件时采用本地频道列表 + var distance = TimeSpan.FromSeconds(int.Parse(ConfigurationManager.AppSettings["Player.ChannelInfoExpireSeconds"])); + if (localChannelInfo != null && DateTime.Now - localChannelInfoTime < distance) + { + return localChannelInfo; + } + } + } + catch (Exception ex) + { + Debug.WriteLine(DateTime.Now + " 获取本地频道列表失败:" + ex.Message); + } + + //尝试获取服务器频道列表 + int tryCount = 0; + int tryCountMax = int.Parse(ConfigurationManager.AppSettings["Player.ChannelInfoRetryCount"]); + while (true) + { + //获取服务器频道列表多次失败后采用本地频道列表 + if (tryCount == tryCountMax && localChannelInfo != null) return localChannelInfo; + + ++tryCount; + + Debug.WriteLine(DateTime.Now + " 获取频道列表……"); + var file = new ConnectionBase {UseGzip = true}.Get( + string.Format(ConfigurationManager.AppSettings["Player.ChannelInfoUrlFormat"], + typeof (Player).Assembly.GetName().Version)); + Debug.WriteLine(DateTime.Now + " 获取频道列表完成"); + if (string.IsNullOrEmpty(file)) + { + TakeABreak(); + continue; + } + var channelInfo = new ChannelInfo(Json.JsonHelper.FromJson(file)); + if (!channelInfo.IsEffective) + { + Debug.WriteLine(DateTime.Now + " 获取频道列表失败"); + TakeABreak(); + } + else + { + Debug.WriteLine(DateTime.Now + " 获取频道列表成功"); + try + { + File.WriteAllText(localPath, file); + } + catch (Exception ex) + { + Debug.WriteLine(DateTime.Now + " 写入本地频道列表失败:" + ex.Message); + } + return channelInfo; + } + } + } + + /// + /// 刚启动时选择一个频道 + /// + private void ChooseChannelAtStartup() + { + if (Settings.LastChannel != null) + { + bool selected = false; + Channel firstChannel = Settings.LastChannel; + if (firstChannel.IsPersonal && UserAssistant.IsLoggedOn ||firstChannel.IsSpecial) + selected = true; + //else if (firstChannel.IsDj) + { + foreach (Channel channel in ChannelInfo.Dj) + if (channel == firstChannel) + { + selected = true; + } + } + //else + { + foreach (Channel channel in ChannelInfo.Public) + if (channel == firstChannel) + { + selected = true; + } + } + if (selected) + CurrentChannel = firstChannel; + } + if (CurrentChannel == null) + CurrentChannel = ChannelInfo.Public.First(); + } + + #endregion + + #region 播放器控制 + + /// + /// 码率设置已改变 + /// + public void ProRateChanged() + { + Report("n", false); + } + + /// + /// 歌曲自然播放完毕,添加播放记录或请求新播放列表。 + /// type=e + /// Played + /// + public void CurrentSongFinishedPlaying() + { + RaiseStopedEvent(); + if (UserAssistant.IsLoggedOn) + { + ++Settings.User.Played; + RaisePlayRecordChangedEvent(); + } + ChangeToNextSong("e"); + } + /// + /// 媒体加载失败时请调用此方法 + /// 此方法与Skip()方法唯一的不同是不会触发Stoped事件 + /// 如果媒体加载失败时调用Skip(),会触发Stoped事件,然后会执行MediaElement的Stop()方法,然后再次失败,于是Skip方法会循环调用 + /// + public void MediaFailed() + { + if (CurrentSong == null) return; + if (_skipping) return; + ChangeToNextSong("s"); + } + /// + /// 跳过当前歌曲 + /// type=s + /// Skip + /// + public void Skip() + { + if (CurrentSong == null) return; + if (_skipping) return; + RaiseStopedEvent(); + ChangeToNextSong("s"); + } + /// + /// 喜欢这首歌 + /// + void Like() + { + if (CurrentSong == null) return; + if (CurrentSong.Like) return; + CurrentSong.Like = true; + if (UserAssistant.IsLoggedOn) + { + ++Settings.User.Liked; + RaisePlayRecordChangedEvent(); + } + Report("r", false); + } + /// + /// 不喜欢这首歌 + /// + void Unlike() + { + if (CurrentSong == null) return; + if (!CurrentSong.Like) return; + CurrentSong.Like = false; + if (UserAssistant.IsLoggedOn) + { + --Settings.User.Liked; + RaisePlayRecordChangedEvent(); + } + Report("u", false); + } + /// + /// 对当前音乐标记不再播放 + /// type=b + /// Ban + /// + public void Never() + { + if (CurrentSong == null) return; + if (_neverring) return; + RaiseStopedEvent(); + if (UserAssistant.IsLoggedOn) + { + ++Settings.User.Banned; + RaisePlayRecordChangedEvent(); + } + + ChangeToNextSong("b"); + } + /// + /// 暂停 + /// + void Pause() + { + if (CurrentSong == null) return; + IsPlaying = false; + _pauseTime = DateTime.Now; + RaisePausedEvent(); + } + /// + /// 播放。若暂停时长超过半个小时,则播放一个新的播放列表 + /// + void Play() + { + if (CurrentSong == null) return; + IsPlaying = true; + RaisePlayedEvent(); + /* 由于豆瓣电台的音乐地址都是临时的,所以超过一定时间后按道理应该立即重新获取一个全新的播放列表, + * 但考虑到播放体验的流畅性,这里仍然播放当前的音乐,但是_playListSongs要更换, + * */ + if ((DateTime.Now - _pauseTime).TotalMinutes > 30) + { + Report("n", false); + } + } + + #endregion + + #region 成员方法 + + /// + /// 获取下一首音乐的URL + /// + /// + public string GetNextSongUrl() + { + lock (_playListSongs) + { + if (_playListSongs.Count > 0) + return _playListSongs.First().FileUrl; + else return null; + } + } + /// + /// 读取偏好设置 + /// + void LoadSettings() + { + Settings = Core.Settings.Load(); + Settings.Current = Settings; + } + /// + /// 保存偏好设置 + /// + public void SaveSettings() + { + Settings.Save(); + SaveCookies(); + } + /// + /// 保存Cookies + /// + /// 成功与否 + static bool SaveCookies() + { + return ConnectionBase.SaveCookies(); + } + + /// + /// 获取全新的播放列表 + /// type=n + /// New + /// + void NewPlayList() //根据douban.fm的网络传输观察,只有全新的播放列表才利用context信息,其他播放列表请求都不传输context + { + if (!IsInitialized) return; + ChangeToNextSong("n"); + } + + void Report(string type, bool changeCurrentSong = true) + { + ThreadPool.QueueUserWorkItem(new WaitCallback((state) => + { + lock (workLock) + { + if (type == "s") + { + _skipping = true; + } + if (type == "b") + { + _neverring = true; + } + PlayList pl = null; + PlayerState ps = GetPlayerState(); + while (true) + { + pl = PlayList.GetPlayList(ps, type); + if ((type == "p" || type == "n") && pl.Count == 0) TakeABreak(); + else if (type == "e") break; + else if (ps.CurrentChannel.IsDj) break; + else if (pl.Count == 0) TakeABreak(); + else break; + } + PlayerState ps2 = GetPlayerState(); + if (ps.CurrentChannel == ps2.CurrentChannel) + { + if (pl.Count > 0) + { + ChangePlayListSongs(pl); + } + if (changeCurrentSong) + { + ChangeCurrentSong(); + } + } + if (type == "s") + { + _skipping = false; + } + if (type == "b") + { + _neverring = false; + } + } + })); + } + + void ChangeToNextSong(string type) + { + Report(type); + } + + /// + /// 更换播放列表队列 + /// + /// 新播放列表 + void ChangePlayListSongs(PlayList pl) + { + lock (_playListSongs) + { + _playListSongs.Clear(); + foreach (var song in pl) + _playListSongs.Enqueue(song); + } + } + /// + /// 更换当前播放的音乐 + /// + void ChangeCurrentSong() + { + PlayList pl = null; + PlayerState ps = GetPlayerState(); + while (_playListSongs.Count == 0) + { + pl = PlayList.GetPlayList(ps, "p"); + if (pl.Count == 0) + TakeABreak(); + else + { + ChangePlayListSongs(pl); + break; + } + } + lock (_playListSongs) + Dispatcher.Invoke(new Action(() => { CurrentSong = _playListSongs.Dequeue(); })); + } + /// + /// 网络发送间歇 + /// + static void TakeABreak() + { + Thread.Sleep(5000); + } + + /// + /// 获取当前状态,用于向线程池加入任务时传递参数 + /// + /// + private PlayerState GetPlayerState() + { + PlayerState ps = null; + if (CheckAccess()) + ps = new PlayerState(Settings.User == null ? null : (User) Settings.User.Clone(), + CurrentChannel == null ? null : (Channel) CurrentChannel.Clone(), + CurrentSong == null ? null : (Song) CurrentSong.Clone()); + else + Dispatcher.Invoke(new Action(() => { ps = GetPlayerState(); })); + return ps; + } + + /// + /// 是否可以加入收藏 + /// + /// 频道 + public bool CanAddToFavorites(Channel channel) + { + if (!IsInitialized || channel == null) return false; + if (channel.IsPersonal && !channel.IsSpecial) + return false; + return !Settings.FavoriteChannels.Contains(channel); + } + /// + /// 是否可以取消收藏 + /// + /// 频道 + public bool CanRemoveFromFavorites(Channel channel) + { + if (!IsInitialized || channel == null) return false; + if (channel.IsPersonal && !channel.IsSpecial) + return false; + return Settings.FavoriteChannels.Contains(channel); + } + /// + /// 将频道加入收藏 + /// + /// 频道 + /// 是否成功 + public bool AddToFavorites(Channel channel) + { + if (!CanAddToFavorites(channel)) + { + return false; + } + else + { + Settings.FavoriteChannels.Add(channel); + return true; + } + } + /// + /// 将频道从收藏中删除 + /// + /// 频道 + /// 是否成功 + public bool RemoveFromFavorites(Channel channel) + { + if (!CanRemoveFromFavorites(channel)) + { + return false; + } + else + { + Settings.FavoriteChannels.Remove(channel); + return true; + } + } + + #endregion + + /// + /// 记录播放器的状态 + /// + internal class PlayerState + { + public User CurrentUser { get; set; } + /// + /// 当前频道 + /// + public Channel CurrentChannel { get; set; } + /// + /// 当前歌曲 + /// + public Song CurrentSong { get; set; } + + internal PlayerState(User currentUser, Channel currentChannel, Song currentSong) + { + CurrentUser = currentUser; + CurrentChannel = currentChannel; + CurrentSong = currentSong; + } + } + } +} diff --git a/DoubanFM.Core/Player/ProRate.cs b/DoubanFM.Core/Player/ProRate.cs new file mode 100644 index 0000000..8140466 --- /dev/null +++ b/DoubanFM.Core/Player/ProRate.cs @@ -0,0 +1,9 @@ +namespace DoubanFM.Core +{ + public enum ProRate + { + Kbps64, + Kbps128, + Kbps192 + } +} diff --git a/DoubanFM.Core/Player/Song.cs b/DoubanFM.Core/Player/Song.cs new file mode 100644 index 0000000..60d9698 --- /dev/null +++ b/DoubanFM.Core/Player/Song.cs @@ -0,0 +1,156 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DoubanFM.Core +{ + /// + /// 歌曲 + /// + public class Song : ICloneable, IEquatable + { + /// + /// 音乐文件URL + /// + public string FileUrl { get; set; } + /// + /// 标题 + /// + public string Title { get; set; } + /// + /// 表演者 + /// + public string Artist { get; set; } + /// + /// 专辑 + /// + public string Album { get; set; } + /// + /// 唱片公司 + /// + public string Company { get; set; } + /// + /// 封面URL + /// + public string Picture { get; set; } + /// + /// 长度 + /// + public TimeSpan Length { get; set; } + /// + /// 发行年 + /// + public string PublicTime { get; set; } + /// + /// 专辑的豆瓣资料页面 + /// + public string AlbumInfo { get; set; } + public string SSId { get; set; } + /// + /// 平均评分 + /// + public double Rate { get; set; } + public string SourceUrl { get; set; } + /// + /// 普通音乐应该是"",广告应该是"T" + /// + public string Type { get; set; } + /// + /// 歌曲ID + /// + public string SongId { get; set; } + /// + /// 专辑ID + /// + public string AlbumId { get; set; } + /// + /// 当前用户喜欢与否 + /// + public bool Like { get; set; } + + /// + /// 是否是广告 + /// + public bool IsAd { get { return Type == "T"; } } + + private Song() + { + } + + internal Song(DoubanFM.Core.Json.Song song) + { + FileUrl = song.url; + Title = song.title; + Artist = song.artist; + Album = song.albumtitle; + Company = song.company; + Picture = song.picture; + Length = TimeSpan.FromSeconds(song.length); + PublicTime = song.public_time; + AlbumInfo = song.album; + SSId = song.ssid; + Rate = song.rating_avg; + SourceUrl = song.source_url; + Type = song.subtype; + SongId = song.sid; + AlbumId = song.aid; + Like = song.like; + } + + public object Clone() + { + return this.MemberwiseClone(); + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append(Title); + sb.Append(" - "); + sb.Append(Artist); + sb.Append(" - "); + sb.Append(Album); + return sb.ToString(); + } + + public bool Equals(Song other) + { + if (Object.ReferenceEquals(other, null)) + return false; + if (Object.ReferenceEquals(this, other)) + return true; + return this.FileUrl == other.FileUrl; + } + + public override bool Equals(object obj) + { + return Equals(obj as Song); + } + + public override int GetHashCode() + { + if (FileUrl == null) return 0; + return FileUrl.GetHashCode(); + } + + public static bool operator ==(Song lhs, Song rhs) + { + if (Object.ReferenceEquals(lhs, null)) + if (Object.ReferenceEquals(rhs, null)) + return true; + else return false; + return lhs.Equals(rhs); + } + public static bool operator !=(Song lhs, Song rhs) + { + return !(lhs == rhs); + } + } +} \ No newline at end of file diff --git a/DoubanFM.Core/Player/User.cs b/DoubanFM.Core/Player/User.cs new file mode 100644 index 0000000..5b4f4ee --- /dev/null +++ b/DoubanFM.Core/Player/User.cs @@ -0,0 +1,193 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Runtime.Serialization; + +namespace DoubanFM.Core +{ + /// + /// 用户 + /// + [Serializable] + public class User : ISerializable, ICloneable + { + /// + /// 用户名 + /// + public string Username { get; set; } + /// + /// 密码 + /// + public string Password { get; set; } + /// + /// 用户ID + /// + public string UserID { get; set; } + /// + /// 昵称 + /// + public string Nickname { get; set; } + /// + /// 电子邮箱 + /// + public string Email { get; set; } + /// + /// Token + /// + public string Token { get; set; } + /// + /// Expire + /// + public string Expire { get; set; } + /// + /// 累计播放数量 + /// + public int Played { get; set; } + /// + /// 加红心数量 + /// + public int Liked { get; set; } + /// + /// 不再播放数量 + /// + public int Banned { get; set; } + + /// + /// 是否使用Pro服务 + /// + public bool IsPro { get; set; } + + /// + /// Pro服务比特率设置 + /// + public ProRate ProRate { get; set; } + + internal User(string username, string password) + { + Username = username; + Password = password; + } + + private User() + { + Username = string.Empty; + Password = string.Empty; + } + + protected User(SerializationInfo info, StreamingContext context) + { + try + { + Username = info.GetString("Username"); + } + catch + { + } + try + { + Password = Encryption.Decrypt(info.GetString("Password")); + } + catch + { + } + try + { + UserID = info.GetString("UserID"); + } + catch + { + } + try + { + Nickname = info.GetString("Nickname"); + } + catch + { + } + try + { + Email = info.GetString("Email"); + } + catch + { + } + try + { + Token = info.GetString("Token"); + } + catch + { + } + try + { + Expire = info.GetString("Expire"); + } + catch + { + } + try + { + Played = info.GetInt32("Played"); + } + catch + { + } + try + { + Liked = info.GetInt32("Liked"); + } + catch + { + } + try + { + Banned = info.GetInt32("Banned"); + } + catch + { + } + try + { + IsPro = info.GetBoolean("IsPro"); + } + catch{} + try + { + ProRate = (ProRate) info.GetValue("ProRate", typeof (ProRate)); + } + catch + { + + } + } + + public virtual void GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("Username", Username); + info.AddValue("Password", Encryption.Encrypt(Password ?? string.Empty)); + info.AddValue("UserID", UserID); + info.AddValue("Nickname", Nickname); + info.AddValue("Email", Email); + info.AddValue("Token", Token); + info.AddValue("Expire", Expire); + info.AddValue("Played", Played); + info.AddValue("Liked", Liked); + info.AddValue("Banned", Banned); + info.AddValue("IsPro", IsPro); + info.AddValue("ProRate", ProRate); + } + + public object Clone() + { + return MemberwiseClone(); + } + } +} diff --git a/DoubanFM.Core/Player/UserAssistant.cs b/DoubanFM.Core/Player/UserAssistant.cs new file mode 100644 index 0000000..5e0b6c0 --- /dev/null +++ b/DoubanFM.Core/Player/UserAssistant.cs @@ -0,0 +1,555 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows; +using System.Threading; +using System.Diagnostics; +using DoubanFM.Core.Json; + +namespace DoubanFM.Core +{ + /// + /// 处理用户的登录、注销等请求 + /// + public class UserAssistant : DependencyObject + { + #region 依赖项属性 + + public static readonly DependencyProperty CurrentStateProperty = DependencyProperty.Register("CurrentState", typeof(State), typeof(UserAssistant)); + public static readonly DependencyProperty IsLoggedOnProperty = DependencyProperty.Register("IsLoggedOn", typeof(bool), typeof(UserAssistant)); + public static readonly DependencyProperty IsLoggedOffProperty = DependencyProperty.Register("IsLoggedOff", typeof(bool), typeof(UserAssistant)); + public static readonly DependencyProperty IsLoggingOnProperty = DependencyProperty.Register("IsLoggingOn", typeof(bool), typeof(UserAssistant)); + public static readonly DependencyProperty IsLoggingOffProperty = DependencyProperty.Register("IsLoggingOff", typeof(bool), typeof(UserAssistant)); + //public static readonly DependencyProperty HasCaptchaProperty = DependencyProperty.Register("HasCaptcha", typeof(bool), typeof(UserAssistant)); + //public static readonly DependencyProperty CaptchaUrlProperty = DependencyProperty.Register("CaptchaUrl", typeof(string), typeof(UserAssistant)); + public static readonly DependencyProperty ShowLogOnFailedHintProperty = DependencyProperty.Register("ShowLogOnFailedHint", typeof(bool), typeof(UserAssistant)); + public static readonly DependencyProperty LogOnFailedMessageProperty = DependencyProperty.Register("LogOnFailedMessage", typeof(string), typeof(UserAssistant)); + + #endregion + + #region 属性 + + /// + /// 用户 + /// + public Settings Settings { get; internal set; } + /// + /// 登录状态 + /// + public enum State + { + /// + /// 未知 + /// + Unknown, + /// + /// 已注销 + /// + LoggedOff, + /// + /// 正在登录 + /// + LoggingOn, + /// + /// 已登录 + /// + LoggedOn, + /// + /// 正在注销 + /// + LoggingOff + }; + /// + /// 当前状态 + /// + public State CurrentState + { + get { return (State)GetValue(CurrentStateProperty); } + set + { + if (CurrentState != value) + { + State lastState = CurrentState; + SetValue(CurrentStateProperty, value); + SetValue(IsLoggedOnProperty, CurrentState == State.LoggedOn); + SetValue(IsLoggedOffProperty, CurrentState == State.LoggedOff); + SetValue(IsLoggingOnProperty, CurrentState == State.LoggingOn); + SetValue(IsLoggingOffProperty, CurrentState == State.LoggingOff); + RaiseCurrentStateChangedEvent(lastState, value); + //Settings.LastTimeLoggedOn = IsLoggedOn; + ShowLogOnFailedHint = false; + if (lastState == State.LoggingOn) + if (CurrentState == State.LoggedOn) + RaiseLogOnSucceedEvent(); + else if (CurrentState == State.LoggedOff) + { + ShowLogOnFailedHint = true; + RaiseLogOnFailedEvent(); + } + if (lastState == State.LoggingOff) + if (CurrentState == State.LoggedOff) + RaiseLogOffSucceedEvent(); + else if (CurrentState == State.LoggedOn) + RaiseLogOffFailedEvent(); + ////假定登录时始终需要验证码 + //if (lastState == State.LoggingOn && CurrentState == State.LoggedOff) // && (HasCaptcha || ErrorNo == 1011)) + //{ + // UpdateCaptcha(); + //} + ////假定登录时始终需要验证码 + //else if (lastState == State.LoggingOff && CurrentState == State.LoggedOff)// && HasCaptcha) + //{ + // UpdateCaptcha(); + //} + } + } + } + /// + /// 是否已登录 + /// + public bool IsLoggedOn { get { return (bool)GetValue(IsLoggedOnProperty); } } + /// + /// 是否正在登录 + /// + public bool IsLoggingOn { get { return (bool)GetValue(IsLoggingOnProperty); } } + /// + /// 是否已注销 + /// + public bool IsLoggedOff { get { return (bool)GetValue(IsLoggedOffProperty); } } + /// + /// 是否正在注销 + /// + public bool IsLoggingOff { get { return (bool)GetValue(IsLoggingOffProperty); } } + /// + /// 是否显示登录失败的提示信息 + /// + public bool ShowLogOnFailedHint + { + get { return (bool)GetValue(ShowLogOnFailedHintProperty); } + private set { SetValue(ShowLogOnFailedHintProperty, value); } + } + /// + /// 登录失败的提示消息 + /// + public string LogOnFailedMessage + { + get { return (string)GetValue(LogOnFailedMessageProperty); } + protected set { SetValue(LogOnFailedMessageProperty, value); } + } + ///// + ///// 验证码URL + ///// + //public string CaptchaUrl + //{ + // get + // { + // return (string)GetValue(CaptchaUrlProperty); + // } + // protected set + // { + // SetValue(CaptchaUrlProperty, value); + // } + //} + ///// + ///// 是否要求输入验证码 + ///// + //public bool HasCaptcha + //{ + // get { return (bool)GetValue(HasCaptchaProperty); } + // set { SetValue(HasCaptchaProperty, value); } + //} + + #endregion + + #region 事件 + + /// + /// 当登录成功时发生。 + /// + public event EventHandler LogOnSucceed; + /// + /// 当注销成功时发生。 + /// + public event EventHandler LogOffSucceed; + /// + /// 当登录失败时发生。 + /// + public event EventHandler LogOnFailed; + /// + /// 当注销失败时发生。 + /// + public event EventHandler LogOffFailed; + /// + /// 当状态改变时发生。 + /// + public event DependencyPropertyChangedEventHandler CurrentStateChanged; + void RaiseLogOnSucceedEvent() + { + if (LogOnSucceed != null) + LogOnSucceed(this, EventArgs.Empty); + } + void RaiseLogOffSucceedEvent() + { + if (LogOffSucceed != null) + LogOffSucceed(this, EventArgs.Empty); + } + void RaiseLogOnFailedEvent() + { + if (LogOnFailed != null) + LogOnFailed(this, EventArgs.Empty); + } + void RaiseLogOffFailedEvent() + { + if (LogOffFailed != null) + LogOffFailed(this, EventArgs.Empty); + } + void RaiseCurrentStateChangedEvent(State oldState, State newState) + { + if (CurrentStateChanged != null) + CurrentStateChanged(this, new DependencyPropertyChangedEventArgs(CurrentStateProperty, oldState, newState)); + } + + #endregion + + #region 私有变量 + + ///// + ///// 验证码ID + ///// + //private string captchaId; + + #endregion + + #region 成员方法 + + ///// + ///// 更新验证码 + ///// + //public void UpdateCaptcha() + //{ + // HasCaptcha = true; + // captchaId = null; + // CaptchaUrl = null; + // ThreadPool.QueueUserWorkItem(new WaitCallback((state) => + // { + // captchaId = new ConnectionBase().Get("http://douban.fm/j/new_captcha"); + // Dispatcher.BeginInvoke(new Action(() => + // { + // if (string.IsNullOrEmpty(captchaId)) + // { + // HasCaptcha = false; + // captchaId = null; + // CaptchaUrl = null; + // } + // else + // { + // captchaId = captchaId.Trim('\"'); + // HasCaptcha = true; + // CaptchaUrl = @"http://douban.fm/misc/captcha?size=m&id=" + captchaId; + // } + // })); + // })); + //} + + ///// + ///// 根据douban.fm的主页的HTML代码更新登录状态 + ///// + ///// HTML文件 + //internal void Update(string html) + //{ + // if (!string.IsNullOrEmpty(html)) + // { + // //获取昵称和播放记录 + // Match match2 = Regex.Match(html, @"""user_name""[^<>]*?>(?!{{)([^<>]*?)\s*<", RegexOptions.Singleline); + + // string nickname = match2.Groups[1].Value; + // Match match3 = Regex.Match(html, @"累积收听.*?(\d+).*?首"); + // int played = 0; + // int.TryParse(match3.Groups[1].Value, out played); + // Match match4 = Regex.Match(html, @"加红心.*?(\d+).*?首"); + // int liked = 0; + // int.TryParse(match4.Groups[1].Value, out liked); + // Match match5 = Regex.Match(html, @"(\d+).*?首不再播放"); + // int banned = 0; + // int.TryParse(match5.Groups[1].Value, out banned); + + // //更改属性 + // Dispatcher.Invoke(new Action(() => + // { + // /*System.Diagnostics.Debug.WriteLine("**********************************************************************"); + // System.Diagnostics.Debug.WriteLine(DateTime.Now + " 以下是本次“登录/注销”返回的结果页面"); + // System.Diagnostics.Debug.Indent(); + // System.Diagnostics.Debug.WriteLine(html); + // System.Diagnostics.Debug.Unindent(); + // System.Diagnostics.Debug.WriteLine("**********************************************************************"); + // */ + // if (!string.IsNullOrEmpty(nickname)) + // { + // Settings.User.Nickname = nickname; + // Settings.User.Played = played; + // Settings.User.Liked = liked; + // Settings.User.Banned = banned; + // System.Diagnostics.Debug.WriteLine("已登录"); + // CurrentState = State.LoggedOn; + // } + // else + // { + // Settings.User.Nickname = string.Empty; + // System.Diagnostics.Debug.WriteLine("已注销"); + // CurrentState = State.LoggedOff; + // } + // })); + // } + // else + // Dispatcher.Invoke(new Action(() => + // { + // if (CurrentState == State.LoggingOn) CurrentState = State.LoggedOff; + // else if (CurrentState == State.LoggingOff) CurrentState = State.LoggedOn; + // else if (CurrentState == State.Unknown) CurrentState = State.LoggedOff; + // else CurrentState = State.LoggedOff; + // })); + //} + /// + /// 根据服务器返回的登录结果更新登录状态 + /// + private void UpdateWhenLogOn(LogOnResult result) + { + Debug.Assert(result != null, "result != null"); + string errorMessage = null; + + if (!result.r) + { + Settings.User.UserID = result.user_id; + Settings.User.Token = result.token; + Settings.User.Expire = result.expire; + Settings.User.Nickname = result.user_name; + Settings.User.Email = result.email; + + UpdateUserInfo(); + } + else + { + Debug.WriteLine(result.err); + switch (result.err) + { + case "invalid_username": + errorMessage = Resources.Resources.InvalidUsername; + break; + case "wrong_password": + errorMessage = Resources.Resources.WrongPassword; + break; + case null: + case "": + case "unknown_error": + errorMessage = Resources.Resources.UnknownError; + break; + default: + errorMessage = result.err; + break; + } + } + Dispatcher.Invoke(new Action(() => + { + LogOnFailedMessage = errorMessage; + if (!string.IsNullOrEmpty(Settings.User.Token)) + { + CurrentState = State.LoggedOn; + } + else + { + ResetUser(); + } + })); + } + + /// + /// 登录 + /// + public void LogOn() + { + if (CurrentState != State.LoggedOff) return; + CurrentState = State.LoggingOn; + var username = Settings.User.Username ?? string.Empty; + var password = Settings.User.Password ?? string.Empty; + ThreadPool.QueueUserWorkItem(state => + { + LogOnResult result = null; + List errorMessages = new List(); + if (Regex.Match(username, @"^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*$", RegexOptions.IgnoreCase).Success) + { + var resultEmail = LogOnWithEmail(username, password); + if (resultEmail != null) + { + if (!resultEmail.r) + { + result = resultEmail; + } + else + { + errorMessages.Add(resultEmail.err); + } + } + } + if (result == null) + { + var resultUsername = LogOnWithUsername(username, password); + if (resultUsername != null) + { + if (!resultUsername.r) + { + result = resultUsername; + } + else + { + errorMessages.Add(resultUsername.err); + } + } + } + if (result == null) + { + result = new LogOnResult {r = true}; + var invalidUsername = new[] {"invalid_user_name", "invalidate_email", "wrong_email"}; + errorMessages = + (from message in errorMessages + where !string.IsNullOrEmpty(message) + select invalidUsername.Contains(message) ? "invalid_username" : message).Distinct().ToList(); + if (errorMessages.Count == 0) + { + result.err = "unknown_error"; + } + else + { + result.err = errorMessages.FirstOrDefault(message => message != "invalid_username") ?? + errorMessages[0]; + } + } + UpdateWhenLogOn(result); + }); + } + /// + /// 使用用户名登录 + /// + /// 用户名 + /// 密码 + /// 登录结果 + private LogOnResult LogOnWithUsername(string username, string password) + { + Parameters parameters = new Parameters(); + parameters["app_name"] = "radio_desktop_win"; + parameters["version"] = "100"; + parameters["username"] = username; + parameters["password"] = password; + string file = new ConnectionBase().Post("http://www.douban.com/j/app/login", + Encoding.UTF8.GetBytes(parameters.ToString())); + return JsonHelper.FromJson(file); + } + /// + /// 使用邮箱登录 + /// + /// 邮箱 + /// 密码 + /// 登录结果 + private LogOnResult LogOnWithEmail(string email, string password) + { + Parameters parameters = new Parameters(); + parameters["app_name"] = "radio_desktop_win"; + parameters["version"] = "100"; + parameters["email"] = email; + parameters["password"] = password; + string file = new ConnectionBase().Post("http://www.douban.com/j/app/login", + Encoding.UTF8.GetBytes(parameters.ToString())); + return JsonHelper.FromJson(file); + } + + /// + /// 重置与用户有关的所有附加信息 + /// + private void ResetUser() + { + CurrentState = State.LoggedOff; + Settings.User = new User(Settings.User.Username, Settings.User.Password); + } + /// + /// 注销 + /// + public void LogOff() + { + ResetUser(); + LogOnFailedMessage = null; + } + + /// + /// 初始化用户状态 + /// + public void Initialize() + { + bool loggedOn = false; + bool expired = false; + if (!string.IsNullOrEmpty(Settings.User.UserID) && !string.IsNullOrEmpty(Settings.User.Token) && + !string.IsNullOrEmpty(Settings.User.Expire)) + { + loggedOn = UpdateUserInfo(); + if (!loggedOn) expired = true; + } + Dispatcher.Invoke(new Action(() => + { + CurrentState = loggedOn ? State.LoggedOn : State.LoggedOff; + if (expired) + { + Settings.User = new User(Settings.User.Username, Settings.User.Password); + } + })); + } + + /// + /// 更新用户信息 + /// + /// 是否成功 + private bool UpdateUserInfo() + { + Debug.Assert(!string.IsNullOrEmpty(Settings.User.Token), "!string.IsNullOrEmpty(Settings.User.Token)"); + Parameters parameters = new Parameters(); + parameters["app_name"] = "radio_desktop_win"; + parameters["version"] = "100"; + parameters["user_id"] = Settings.User.UserID; + parameters["token"] = Settings.User.Token; + parameters["expire"] = Settings.User.Expire; + string file = new ConnectionBase().Post("http://www.douban.com/j/app/radio/user_info", + Encoding.UTF8.GetBytes(parameters.ToString())); + var userInfo = JsonHelper.FromJson(file); + if (userInfo == null || userInfo.r) + { + return false; + } + + Settings.User.Played = userInfo.played_num; + Settings.User.Liked = userInfo.liked_num; + Settings.User.Banned = userInfo.banned_num; + if (userInfo.pro_status == "S") + { + if (!Settings.User.IsPro) + { + Settings.User.IsPro = true; + Settings.User.ProRate = ProRate.Kbps64; + } + } + else + { + Settings.User.IsPro = false; + Settings.User.ProRate = ProRate.Kbps64; + } + + return true; + } + + #endregion + } +} diff --git a/DoubanFM.Core/Properties/AssemblyInfo.cs b/DoubanFM.Core/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..e6f9755 --- /dev/null +++ b/DoubanFM.Core/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的常规信息通过以下 +// 特性集控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("DoubanFM.Core")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("K.F.Storm")] +[assembly: AssemblyProduct("豆瓣电台")] +[assembly: AssemblyCopyright("Copyright © 2011 - 2013 K.F.Storm")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +// 将 ComVisible 设置为 false 使此程序集中的类型 +// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, +// 则将该类型上的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("66b6c480-7af5-40c6-b45b-af2b79fca312")] +// 程序集的版本信息由下面四个值组成: +// +// 主版本 +// 次版本 +// 内部版本号 +// 修订号 +// +// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, +// 方法是按如下所示使用“*”: +[assembly: AssemblyVersion("2.1.3.0")] +//[assembly: AssemblyVersion("1.0.0.0")] +//[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/DoubanFM.Core/Resources/Resources.Designer.cs b/DoubanFM.Core/Resources/Resources.Designer.cs new file mode 100644 index 0000000..7833420 --- /dev/null +++ b/DoubanFM.Core/Resources/Resources.Designer.cs @@ -0,0 +1,108 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.18033 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace DoubanFM.Core.Resources { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DoubanFM.Core.Resources.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 使用此强类型资源类,为所有资源查找 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 Invalid username 的本地化字符串。 + /// + internal static string InvalidUsername { + get { + return ResourceManager.GetString("InvalidUsername", resourceCulture); + } + } + + /// + /// 查找类似 I'm listening to {0} - {1} 的本地化字符串。 + /// + internal static string ShareTextPartOne { + get { + return ResourceManager.GetString("ShareTextPartOne", resourceCulture); + } + } + + /// + /// 查找类似 ( From K.F.Storm's DoubanFM {0} - {1} ) 的本地化字符串。 + /// + internal static string ShareTextPartTwo { + get { + return ResourceManager.GetString("ShareTextPartTwo", resourceCulture); + } + } + + /// + /// 查找类似 Unknown error 的本地化字符串。 + /// + internal static string UnknownError { + get { + return ResourceManager.GetString("UnknownError", resourceCulture); + } + } + + /// + /// 查找类似 Incorrect password 的本地化字符串。 + /// + internal static string WrongPassword { + get { + return ResourceManager.GetString("WrongPassword", resourceCulture); + } + } + } +} diff --git a/DoubanFM.Core/Resources/Resources.resx b/DoubanFM.Core/Resources/Resources.resx new file mode 100644 index 0000000..d55bad2 --- /dev/null +++ b/DoubanFM.Core/Resources/Resources.resx @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Invalid username + + + I'm listening to {0} - {1} + + + ( From K.F.Storm's DoubanFM {0} - {1} ) + + + Unknown error + + + Incorrect password + + \ No newline at end of file diff --git a/DoubanFM.Core/Resources/Resources.zh-CN.Designer.cs b/DoubanFM.Core/Resources/Resources.zh-CN.Designer.cs new file mode 100644 index 0000000..e69de29 diff --git a/DoubanFM.Core/Resources/Resources.zh-CN.resx b/DoubanFM.Core/Resources/Resources.zh-CN.resx new file mode 100644 index 0000000..7ba1056 --- /dev/null +++ b/DoubanFM.Core/Resources/Resources.zh-CN.resx @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 用户名错误 + + + 我正在收听 《{0}》 - {1} + + + (来自 K.F.Storm 豆瓣电台{0} - {1}) + + + 未知错误 + + + 密码错误 + + \ No newline at end of file diff --git a/DoubanFM.Core/Settings.cs b/DoubanFM.Core/Settings.cs new file mode 100644 index 0000000..5eb03ee --- /dev/null +++ b/DoubanFM.Core/Settings.cs @@ -0,0 +1,670 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading; +using System.Windows; +using System.Runtime.Serialization; +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; +using System.Windows.Media; +using DoubanFM.Bass; + +namespace DoubanFM.Core +{ + /// + /// 偏好设置 + /// + [Serializable] + public class Settings : DependencyObject, ISerializable + { + #region 依赖项属性 + + //public static readonly DependencyProperty UserProperty = DependencyProperty.Register("User", typeof(User), typeof(Settings)); + //public static readonly DependencyProperty RememberPasswordProperty = DependencyProperty.Register("RememberPassword", typeof(bool), typeof(Settings)); + //public static readonly DependencyProperty AutoLogOnNextTimeProperty = DependencyProperty.Register("AutoLogOnNextTime", typeof(bool), typeof(Settings), new PropertyMetadata(true)); + //public static readonly DependencyProperty RememberLastChannelProperty = DependencyProperty.Register("RememberLastChannel", typeof(bool), typeof(Settings), new PropertyMetadata(true)); + public static readonly DependencyProperty LastChannelProperty = DependencyProperty.Register("LastChannel", typeof(Channel), typeof(Settings)); + public static readonly DependencyProperty IsMutedProperty = DependencyProperty.Register("IsMuted", typeof(bool), typeof(Settings)); + public static readonly DependencyProperty VolumeProperty = DependencyProperty.Register("Volume", typeof(double), typeof(Settings), new PropertyMetadata(1.0)); + public static readonly DependencyProperty SlideCoverWhenMouseMoveProperty = DependencyProperty.Register("SlideCoverWhenMouseMove", typeof(bool), typeof(Settings), new PropertyMetadata(true)); + public static readonly DependencyProperty AlwaysShowNotifyIconProperty = DependencyProperty.Register("AlwaysShowNotifyIcon", typeof(bool), typeof(Settings)); + public static readonly DependencyProperty AutoUpdateProperty = DependencyProperty.Register("AutoUpdate", typeof(bool), typeof(Settings), new PropertyMetadata(true)); + public static readonly DependencyProperty LastTimeCheckUpdateProperty = DependencyProperty.Register("LastTimeCheckUpdate", typeof(DateTime), typeof(Settings), new PropertyMetadata(DateTime.MinValue)); + public static readonly DependencyProperty OpenAlbumInfoWhenClickCoverProperty = DependencyProperty.Register("OpenAlbumInfoWhenClickCover", typeof(bool), typeof(Settings), new PropertyMetadata(false)); + public static readonly DependencyProperty IsSearchFilterEnabledProperty = DependencyProperty.Register("IsSearchFilterEnabled", typeof(bool), typeof(Settings), new PropertyMetadata(true)); + public static readonly DependencyProperty ShowLyricsProperty = DependencyProperty.Register("ShowLyrics", typeof(bool), typeof(Settings), new PropertyMetadata(true)); + public static readonly DependencyProperty TopMostProperty = DependencyProperty.Register("TopMost", typeof(bool), typeof(Settings)); + public static readonly DependencyProperty ScaleTransformProperty = DependencyProperty.Register("ScaleTransform", typeof(double), typeof(Settings), new PropertyMetadata(1.0)); + public static readonly DependencyProperty ProxyKindProperty = DependencyProperty.Register("ProxyKind", typeof(ProxyKinds), typeof(Settings), new PropertyMetadata(ProxyKinds.Default)); + public static readonly DependencyProperty ProxyHostProperty = DependencyProperty.Register("ProxyHost", typeof(string), typeof(Settings)); + public static readonly DependencyProperty ProxyPortProperty = DependencyProperty.Register("ProxyPort", typeof(int), typeof(Settings), new PropertyMetadata(8080)); + public static readonly DependencyProperty ProxyUsernameProperty = DependencyProperty.Register("ProxyUsername", typeof(string), typeof(Settings)); + public static readonly DependencyProperty ProxyPasswordProperty = DependencyProperty.Register("ProxyPassword", typeof(string), typeof(Settings)); + public static readonly DependencyProperty AutoBackgroundProperty = DependencyProperty.Register("AutoBackground", typeof(bool), typeof(Settings), new PropertyMetadata(true)); + public static readonly DependencyProperty BackgroundProperty = DependencyProperty.Register("Background", typeof(Color), typeof(Settings), new PropertyMetadata(ColorConverter.ConvertFromString("#FF1960AF"))); + public static readonly DependencyProperty FirstTimeProperty = DependencyProperty.Register("FirstTime", typeof(bool), typeof(Settings), new PropertyMetadata(false)); + public static readonly DependencyProperty MainWindowFontProperty = DependencyProperty.Register("MainWindowFont", typeof(FontFamily), typeof(Settings), new PropertyMetadata(System.Windows.SystemFonts.MessageFontFamily)); + public static readonly DependencyProperty ShowBalloonWhenSongChangedProperty = DependencyProperty.Register("ShowBalloonWhenSongChanged", typeof(bool), typeof(Settings), new PropertyMetadata(true)); + public static readonly DependencyProperty BackgroundTransparencyProperty = DependencyProperty.Register("BackgroundTransparency", typeof(double), typeof(Settings)); + public static readonly DependencyProperty DownloadSiteProperty = DependencyProperty.Register("DownloadSite", typeof(DownloadSite), typeof(Settings), new PropertyMetadata(Enum.GetValues(typeof(DownloadSite)).Cast().Aggregate((DownloadSite)0, (left, right) => left | right))); + public static readonly DependencyProperty TrimBracketsProperty = DependencyProperty.Register("TrimBrackets", typeof(bool), typeof(Settings), new PropertyMetadata(true)); + public static readonly DependencyProperty SearchAlbumProperty = DependencyProperty.Register("SearchAlbum", typeof(bool), typeof(Settings), new PropertyMetadata(false)); + public static readonly DependencyProperty LocationLeftProperty = DependencyProperty.Register("LocationLeft", typeof(double), typeof(Settings), new PropertyMetadata(double.NaN)); + public static readonly DependencyProperty LocationTopProperty = DependencyProperty.Register("LocationTop", typeof(double), typeof(Settings), new PropertyMetadata(double.NaN)); + public static readonly DependencyProperty SpectrumColorProperty = DependencyProperty.Register("SpectrumColor", typeof(Color), typeof(Settings), new PropertyMetadata(Colors.White)); + public static readonly DependencyProperty SpectrumTransparencyProperty = DependencyProperty.Register("SpectrumTransparency", typeof(double), typeof(Settings), new PropertyMetadata(0.0)); + public static readonly DependencyProperty ShowSpectrumProperty = DependencyProperty.Register("ShowSpectrum", typeof(bool), typeof(Settings), new PropertyMetadata(true)); + public static readonly DependencyProperty AdjustVolumeWithMouseWheelProperty = DependencyProperty.Register("AdjustVolumeWithMouseWheel", typeof(bool), typeof(Settings), new PropertyMetadata(true)); + public static readonly DependencyProperty UserKeyProperty = DependencyProperty.Register("UserKey", typeof(string), typeof(Settings), new PropertyMetadata(Guid.NewGuid().ToString("N"))); + public static readonly DependencyProperty FavoriteChannelsProperty = DependencyProperty.Register("FavoriteChannels", typeof(List), typeof(Settings), new PropertyMetadata(new List())); + //public static readonly DependencyProperty LastTimeLoggedOnProperty = DependencyProperty.Register("LastTimeLoggedOn", typeof(bool), typeof(Settings), new PropertyMetadata(false)); + public static readonly DependencyProperty DeviceProperty = DependencyProperty.Register("Device", typeof(DeviceInfo?), typeof(Settings), new PropertyMetadata(null)); + public static readonly DependencyProperty CultureInfoProperty = DependencyProperty.Register("CultureInfo", typeof(CultureInfo), typeof(Settings), new PropertyMetadata(Thread.CurrentThread.CurrentCulture)); + public static readonly DependencyProperty EnableDownloadRateRestrictionProperty = DependencyProperty.Register("EnableDownloadRateRestriction", typeof(bool), typeof(Settings)); + #endregion + + #region ProxyKinds + /// + /// 代理服务器类型 + /// + public enum ProxyKinds + { + /// + /// 默认代理服务器 + /// + Default = 0, + /// + /// 不使用代理服务器 + /// + None, + /// + /// 自定义代理服务器 + /// + Custom + } + #endregion + + /// + /// 当前应用的设置 + /// + public static Settings Current { get; set; } + + /// + /// 用户 + /// + public User User { get; set; } + + ///// + ///// 记住密码 + ///// + //public bool RememberPassword + //{ + // get { return (bool)GetValue(RememberPasswordProperty); } + // set { SetValue(RememberPasswordProperty, value); } + //} + ///// + ///// 下次自动登录 + ///// + //public bool AutoLogOnNextTime + //{ + // get { return (bool)GetValue(AutoLogOnNextTimeProperty); } + // set { SetValue(AutoLogOnNextTimeProperty, value); } + //} + ///// + ///// 记住最后播放的频道 + ///// + //public bool RememberLastChannel + //{ + // get { return (bool)GetValue(RememberLastChannelProperty); } + // set { SetValue(RememberLastChannelProperty, value); } + //} + /// + /// 最后播放的频道 + /// + public Channel LastChannel + { + get { return (Channel)GetValue(LastChannelProperty); } + set { SetValue(LastChannelProperty, value); } + } + /// + /// 静音 + /// + public bool IsMuted + { + get { return (bool)GetValue(IsMutedProperty); } + set { SetValue(IsMutedProperty, value); } + } + /// + /// 音量 + /// + public double Volume + { + get { return (double)GetValue(VolumeProperty); } + set { SetValue(VolumeProperty, value); } + } + /// + /// 当鼠标移动到封面上时滑动封面 + /// + public bool SlideCoverWhenMouseMove + { + get { return (bool)GetValue(SlideCoverWhenMouseMoveProperty); } + set { SetValue(SlideCoverWhenMouseMoveProperty, value); } + } + /// + /// 总是显示托盘图标 + /// + public bool AlwaysShowNotifyIcon + { + get { return (bool)GetValue(AlwaysShowNotifyIconProperty); } + set { SetValue(AlwaysShowNotifyIconProperty, value); } + } + /// + /// 自动更新 + /// + public bool AutoUpdate + { + get { return (bool)GetValue(AutoUpdateProperty); } + set { SetValue(AutoUpdateProperty, value); } + } + /// + /// 最后一次检查更新的时间 + /// + public DateTime LastTimeCheckUpdate + { + get { return (DateTime)GetValue(LastTimeCheckUpdateProperty); } + set { SetValue(LastTimeCheckUpdateProperty, value); } + } + /// + /// 点击封面时打开专辑的豆瓣资料页面 + /// + public bool OpenAlbumInfoWhenClickCover + { + get { return (bool)GetValue(OpenAlbumInfoWhenClickCoverProperty); } + set { SetValue(OpenAlbumInfoWhenClickCoverProperty, value); } + } + /// + /// 自动剔除搜索结果中无法收听的项目 + /// + public bool IsSearchFilterEnabled + { + get { return (bool)GetValue(IsSearchFilterEnabledProperty); } + set { SetValue(IsSearchFilterEnabledProperty, value); } + } + /// + /// 是否显示歌词 + /// + public bool ShowLyrics + { + get { return (bool)GetValue(ShowLyricsProperty); } + set { SetValue(ShowLyricsProperty, value); } + } + /// + /// 总在最前 + /// + public bool TopMost + { + get { return (bool)GetValue(TopMostProperty); } + set { SetValue(TopMostProperty, value); } + } + /// + /// 缩放 + /// + public double ScaleTransform + { + get { return (double)GetValue(ScaleTransformProperty); } + set { SetValue(ScaleTransformProperty, value); } + } + /// + /// 代理服务器类型 + /// + public ProxyKinds ProxyKind + { + get { return (ProxyKinds)GetValue(ProxyKindProperty); } + set { SetValue(ProxyKindProperty, value); } + } + /// + /// 代理服务器主机名 + /// + public string ProxyHost + { + get { return (string)GetValue(ProxyHostProperty); } + set { SetValue(ProxyHostProperty, value); } + } + /// + /// 代理服务器端口 + /// + public int ProxyPort + { + get { return (int)GetValue(ProxyPortProperty); } + set { SetValue(ProxyPortProperty, value); } + } + /// + /// 代理服务器用户名 + /// + public string ProxyUsername + { + get { return (string)GetValue(ProxyUsernameProperty); } + set { SetValue(ProxyUsernameProperty, value); } + } + /// + /// 代理服务器密码 + /// + public string ProxyPassword + { + get { return (string)GetValue(ProxyPasswordProperty); } + set { SetValue(ProxyPasswordProperty, value); } + } + /// + /// 自动更换窗口背景 + /// + public bool AutoBackground + { + get { return (bool)GetValue(AutoBackgroundProperty); } + set { SetValue(AutoBackgroundProperty, value); } + } + /// + /// 指定的窗口背景色 + /// + public Color Background + { + get { return (Color)GetValue(BackgroundProperty); } + set { SetValue(BackgroundProperty, value); } + } + /// + /// 第一次运行 + /// + public bool FirstTime + { + get { return (bool)GetValue(FirstTimeProperty); } + set { SetValue(FirstTimeProperty, value); } + } + /// + /// 主窗口字体 + /// + public FontFamily MainWindowFont + { + get { return (FontFamily)GetValue(MainWindowFontProperty); } + set { SetValue(MainWindowFontProperty, value); } + } + /// + /// 歌曲改变时弹出气泡 + /// + public bool ShowBalloonWhenSongChanged + { + get { return (bool)GetValue(ShowBalloonWhenSongChangedProperty); } + set { SetValue(ShowBalloonWhenSongChangedProperty, value); } + } + /// + /// 窗口背景透明度 + /// + public double BackgroundTransparency + { + get { return (double)GetValue(BackgroundTransparencyProperty); } + set { SetValue(BackgroundTransparencyProperty, value); } + } + /// + /// 下载网站 + /// + public DownloadSite DownloadSite + { + get { return (DownloadSite)GetValue(DownloadSiteProperty); } + set { SetValue(DownloadSiteProperty, value); } + } + /// + /// 搜索下载时自动剔除歌曲信息中的括号内容 + /// + public bool TrimBrackets + { + get { return (bool)GetValue(TrimBracketsProperty); } + set { SetValue(TrimBracketsProperty, value); } + } + /// + /// 搜索下载时包括专辑信息 + /// + public bool SearchAlbum + { + get { return (bool)GetValue(SearchAlbumProperty); } + set { SetValue(SearchAlbumProperty, value); } + } + + /// + /// 窗口位置Left + /// + public double LocationLeft + { + get { return (double)GetValue(LocationLeftProperty); } + set { SetValue(LocationLeftProperty, value); } + } + + /// + /// 窗口位置Top + /// + public double LocationTop + { + get { return (double)GetValue(LocationTopProperty); } + set { SetValue(LocationTopProperty, value); } + } + /// + /// 指定的频谱颜色 + /// + public Color SpectrumColor + { + get { return (Color)GetValue(SpectrumColorProperty); } + set { SetValue(SpectrumColorProperty, value); } + } + /// + /// 频谱透明度 + /// + public double SpectrumTransparency + { + get { return (double)GetValue(SpectrumTransparencyProperty); } + set { SetValue(SpectrumTransparencyProperty, value); } + } + + /// + /// 是否显示频谱 + /// + public bool ShowSpectrum + { + get { return (bool)GetValue(ShowSpectrumProperty); } + set { SetValue(ShowSpectrumProperty, value); } + } + + /// + /// 是否启用鼠标滚轮调节音量 + /// + public bool AdjustVolumeWithMouseWheel + { + get { return (bool)GetValue(AdjustVolumeWithMouseWheelProperty); } + set { SetValue(AdjustVolumeWithMouseWheelProperty, value); } + } + + /// + /// 标识一个使用本软件的用户 + /// + public string UserKey + { + get { return (string)GetValue(UserKeyProperty); } + set { SetValue(UserKeyProperty, value); } + } + + /// + /// 收藏的频道 + /// + public List FavoriteChannels + { + get { return (List)GetValue(FavoriteChannelsProperty); } + set { SetValue(FavoriteChannelsProperty, value); } + } + + ///// + ///// 最后一次是否成功登录 + ///// + //public bool LastTimeLoggedOn + //{ + // get { return (bool)GetValue(LastTimeLoggedOnProperty); } + // set { SetValue(LastTimeLoggedOnProperty, value); } + //} + + /// + /// 设备(空代表默认设备) + /// + public DeviceInfo? Device + { + get { return (DeviceInfo?)GetValue(DeviceProperty); } + set { SetValue(DeviceProperty, value); } + } + + /// + /// 语言 + /// + public CultureInfo CultureInfo + { + get { return (CultureInfo)GetValue(CultureInfoProperty); } + set { SetValue(CultureInfoProperty, value); } + } + + /// + /// Gets or sets a value indicating whether download rate restriction is enabled. + /// + public bool EnableDownloadRateRestriction + { + get { return (bool)GetValue(EnableDownloadRateRestrictionProperty); } + set { SetValue(EnableDownloadRateRestrictionProperty, value); } + } + + /// + /// 数据保存文件夹 + /// + private static string _dataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"K.F.Storm\豆瓣电台"); + + internal Settings(User user) + { + User = user; + } + internal Settings(string username, string password) + : this(new User(username, password)) { } + internal Settings() + : this("", "") { } + + protected Settings(SerializationInfo info, StreamingContext context) + :this() + { + try { User = (User)info.GetValue("User", typeof(User)); } + catch { } + //try { RememberPassword = info.GetBoolean("RememberPassword"); } + //catch { } + //try { AutoLogOnNextTime = info.GetBoolean("AutoLogOnNextTime"); } + //catch { } + //try { RememberLastChannel = info.GetBoolean("RememberLastChannel"); } + //catch { } + try { LastChannel = (Channel)info.GetValue("LastChannel", typeof(Channel)); } + catch { } + try { IsMuted = info.GetBoolean("IsMuted"); } + catch { } + try { Volume = info.GetDouble("Volume"); } + catch { } + try { SlideCoverWhenMouseMove = info.GetBoolean("SlideCoverWhenMouseMove"); } + catch { } + try { AlwaysShowNotifyIcon = info.GetBoolean("AlwaysShowNotifyIcon"); } + catch { } + try { AutoUpdate = info.GetBoolean("AutoUpdate"); } + catch { } + try { LastTimeCheckUpdate = info.GetDateTime("LastTimeCheckUpdate"); } + catch { } + try { OpenAlbumInfoWhenClickCover = info.GetBoolean("OpenAlbumInfoWhenClickCover"); } + catch { } + try { IsSearchFilterEnabled = info.GetBoolean("IsSearchFilterEnabled"); } + catch { } + try { ShowLyrics = info.GetBoolean("ShowLyrics"); } + catch { } + try { TopMost = info.GetBoolean("TopMost"); } + catch { } + try { ScaleTransform = info.GetDouble("ScaleTransform"); } + catch { } + try { ProxyKind = info.GetBoolean("EnableProxy") ? ProxyKinds.Custom : ProxyKinds.Default; } + catch + { + try + { + ProxyKind = (ProxyKinds)info.GetValue("ProxyKind", typeof(ProxyKinds)); + } + catch + { + ProxyKind = ProxyKinds.Default; + } + } + try { ProxyHost = info.GetString("ProxyHost"); } + catch { } + try { ProxyPort = info.GetInt32("ProxyPort"); } + catch { } + try { ProxyUsername = info.GetString("ProxyUsername"); } + catch { } + try { ProxyPassword = Encryption.Decrypt(info.GetString("ProxyPassword")); } + catch { } + try { AutoBackground = info.GetBoolean("AutoBackground"); } + catch { } + try { Background = (Color)ColorConverter.ConvertFromString(info.GetString("Background")); } + catch { } + try { FirstTime = info.GetBoolean("FirstTime"); } + catch { } + try { MainWindowFont = new FontFamily(info.GetString("MainWindowFont")); } + catch { } + try { ShowBalloonWhenSongChanged = info.GetBoolean("ShowBalloonWhenSongChanged"); } + catch { } + try { BackgroundTransparency = info.GetDouble("BackgroundTransparency"); } + catch { } + try { DownloadSite = (DownloadSite)info.GetValue("DownloadSite", typeof(DownloadSite)); } + catch { } + try { TrimBrackets = info.GetBoolean("TrimBrackets"); } + catch { } + try { SearchAlbum = info.GetBoolean("SearchAlbum"); } + catch { } + try { LocationLeft = info.GetDouble("LocationLeft"); } + catch { } + try { LocationTop = info.GetDouble("LocationTop"); } + catch { } + try { SpectrumColor = (Color)ColorConverter.ConvertFromString(info.GetString("SpectrumColor")); } + catch { } + try { SpectrumTransparency = info.GetDouble("SpectrumTransparency"); } + catch { } + try { ShowSpectrum = info.GetBoolean("ShowSpectrum"); } + catch { } + try { AdjustVolumeWithMouseWheel = info.GetBoolean("AdjustVolumeWithMouseWheel"); } + catch { } + try { UserKey = info.GetString("UserKey"); } + catch { } + try { FavoriteChannels = (List)info.GetValue("FavoriteChannels", typeof(List)); } + catch { } + //try { LastTimeLoggedOn = info.GetBoolean("LastTimeLoggedOn"); } + //catch { } + try { Device = (DeviceInfo?)info.GetValue("Device", typeof(DeviceInfo?)); } + catch { } + try { CultureInfo = (CultureInfo)info.GetValue("CultureInfo", typeof(CultureInfo)); } + catch { } + try { EnableDownloadRateRestriction = info.GetBoolean("EnableDownloadRateRestriction"); } + catch { } + + //向下兼容 + if (!AutoBackground && Background.A != 255) + { + BackgroundTransparency = 1 - (double)Background.A / 255; + Background = Color.FromRgb(Background.R, Background.G, Background.B); + } + } + + public virtual void GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("User", User); + //info.AddValue("RememberPassword", RememberPassword); + //info.AddValue("AutoLogOnNextTime", AutoLogOnNextTime); + //info.AddValue("RememberLastChannel", RememberLastChannel); + info.AddValue("LastChannel", LastChannel); + info.AddValue("IsMuted", IsMuted); + info.AddValue("Volume", Volume); + info.AddValue("SlideCoverWhenMouseMove", SlideCoverWhenMouseMove); + info.AddValue("AlwaysShowNotifyIcon", AlwaysShowNotifyIcon); + info.AddValue("AutoUpdate", AutoUpdate); + info.AddValue("LastTimeCheckUpdate", LastTimeCheckUpdate); + info.AddValue("OpenAlbumInfoWhenClickCover", OpenAlbumInfoWhenClickCover); + info.AddValue("IsSearchFilterEnabled", IsSearchFilterEnabled); + info.AddValue("ShowLyrics", ShowLyrics); + info.AddValue("TopMost", TopMost); + info.AddValue("ScaleTransform", ScaleTransform); + info.AddValue("ProxyKind", ProxyKind); + info.AddValue("ProxyHost", ProxyHost); + info.AddValue("ProxyPort", ProxyPort); + info.AddValue("ProxyUsername", ProxyUsername); + info.AddValue("ProxyPassword", Encryption.Encrypt(ProxyPassword ?? string.Empty)); + info.AddValue("AutoBackground", AutoBackground); + if (Background != null) + { + info.AddValue("Background", Background.ToString()); + } + info.AddValue("FirstTime", FirstTime); + if (MainWindowFont != null) + { + info.AddValue("MainWindowFont", MainWindowFont.ToString()); + } + info.AddValue("ShowBalloonWhenSongChanged", ShowBalloonWhenSongChanged); + info.AddValue("BackgroundTransparency", BackgroundTransparency); + info.AddValue("DownloadSite", DownloadSite); + info.AddValue("TrimBrackets", TrimBrackets); + info.AddValue("SearchAlbum", SearchAlbum); + info.AddValue("LocationLeft", LocationLeft); + info.AddValue("LocationTop", LocationTop); + if (SpectrumColor != null) + { + info.AddValue("SpectrumColor", SpectrumColor.ToString()); + } + info.AddValue("SpectrumTransparency", SpectrumTransparency); + info.AddValue("ShowSpectrum", ShowSpectrum); + info.AddValue("AdjustVolumeWithMouseWheel", AdjustVolumeWithMouseWheel); + info.AddValue("UserKey", UserKey); + info.AddValue("FavoriteChannels", FavoriteChannels); + //info.AddValue("LastTimeLoggedOn", LastTimeLoggedOn); + info.AddValue("Device", Device); + info.AddValue("CultureInfo", CultureInfo); + info.AddValue("EnableDownloadRateRestriction", EnableDownloadRateRestriction); + } + + /// + /// 读取设置 + /// + internal static Settings Load() + { + Settings settings = null; + try + { + using (FileStream stream = File.OpenRead(Path.Combine(_dataFolder, "Settings.dat"))) + { + BinaryFormatter formatter = new BinaryFormatter(); + settings = (Settings)formatter.Deserialize(stream); + } + } + catch (Exception ex) + { + settings = new Settings(); + if (ex is FileNotFoundException || ex is DirectoryNotFoundException) + { + settings.FirstTime = true; + } + } + return settings; + } + /// + /// 保存设置 + /// + internal void Save() + { + string tempPassword = User.Password; + //if (!RememberPassword) + User.Password = ""; + //Channel tempLastChannel = LastChannel; + //if (!RememberLastChannel) LastChannel = null; + + try + { + if (!Directory.Exists(_dataFolder)) + Directory.CreateDirectory(_dataFolder); + using (FileStream stream = File.OpenWrite(Path.Combine(_dataFolder, "Settings.dat"))) + { + BinaryFormatter formatter = new BinaryFormatter(); + formatter.Serialize(stream, this); + } + } + catch { } + + User.Password = tempPassword; + //LastChannel = tempLastChannel; + } + } +} \ No newline at end of file diff --git a/DoubanFM.Core/Share.cs b/DoubanFM.Core/Share.cs new file mode 100644 index 0000000..20a90a1 --- /dev/null +++ b/DoubanFM.Core/Share.cs @@ -0,0 +1,292 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DoubanFM.Core +{ + /// + /// 分享 + /// + public class Share + { + /// + /// 分享网站 + /// + public enum Sites + { + /// + /// 无分享网站,仅复制网址 + /// + None, + /// + /// 豆瓣 + /// + Douban, + /// + /// 新浪微博 + /// + Weibo, + /// + /// MSN + /// + Msn, + /// + /// 开心网 + /// + Kaixin, + /// + /// 人人网 + /// + Renren, + /// + /// 腾讯微博 + /// + TencentWeibo, + /// + /// 饭否 + /// + Fanfou, + /// + /// Facebook + /// + Facebook, + /// + /// Twitter + /// + Twitter, + /// + /// QQ空间 + /// + Qzone + } + + /// + /// 分享的歌曲 + /// + public Song Song { get; private set; } + + /// + /// 歌曲所在的频道 + /// + public Channel Channel { get; private set; } + + /// + /// 分享的网站 + /// + public Sites? Site { get; set; } + + /// + /// 分享的内容 + /// + public string Text { get; set; } + + /// + /// 分享的内容(不包含软件的下载地址) + /// + public string TextWithoutSource { get; set; } + + /// + /// 分享的链接 + /// + public string Url + { + get + { + return _songInfo.Url; + } + } + + /// + /// 包含了分享需要的歌曲信息 + /// + private ShareSongInfo _songInfo; + + /// + /// 生成 class 的新实例。 + /// + /// 歌曲 + /// 频道 + /// 网站 + public Share(Song song, Channel channel, Sites site) + { + if (song == null) + throw new ArgumentNullException("song"); + if (channel == null) + throw new ArgumentNullException("channel"); + Song = song; + Channel = channel; + Site = site; + + _songInfo = ShareSongInfo.GetInfo(song, channel); + Text = GetShareText(_songInfo.SongName, _songInfo.ArtistName, _songInfo.ChannelName); + TextWithoutSource = GetShareText(_songInfo.SongName, _songInfo.ArtistName, _songInfo.ChannelName, false); + } + + /// + /// 生成 class 的新实例。 + /// + /// 播放器 + /// 网站 + public Share(Player player, Sites site) + : this(player.CurrentSong, player.CurrentChannel, site) + { } + + /// + /// 生成 class 的新实例。 + /// + /// 歌曲 + /// 频道 + public Share(Song song, Channel channel) + : this(song, channel, Sites.None) + { } + + /// + /// 生成 class 的新实例。 + /// + /// 播放器 + public Share(Player player) + : this(player, Sites.None) + { } + + /// + /// 获取用于显示的网站排序 + /// + /// + public static Sites[] GetSortedSites() + { + return new Sites[] { Sites.None, Sites.Douban, Sites.Weibo, Sites.Msn, Sites.Kaixin, Sites.Renren, Sites.Qzone, Sites.TencentWeibo, Sites.Fanfou, Sites.Facebook, Sites.Twitter }; + } + + /// + /// 获取分享链接 + /// + public string GetShareLink() + { + if (Site == null) + throw new Exception("没有设定分享网站。"); + Parameters parameters = new Parameters(true); + string url = null; + + switch (Site) + { + case Sites.None: + throw new InvalidOperationException("复制网址模式不能获取分享链接"); + //break; + case Sites.Douban: + parameters["name"] = _songInfo.SongName; + parameters["href"] = _songInfo.Url; + parameters["image"] = _songInfo.CoverUrl; + parameters["text"] = ""; + parameters["desc"] = GetShareTextPartTwo(_songInfo.ChannelName); + parameters["apikey"] = "0c2e1df44f97c4eb248a59dceec74ec1"; + url = ConnectionBase.ConstructUrlWithParameters("http://shuo.douban.com/!service/share", parameters); + break; + case Sites.Weibo: + parameters["appkey"] = "1075899032"; + parameters["url"] = _songInfo.Url; + parameters["title"] = TextWithoutSource; + parameters["content"] = "utf-8"; + parameters["pic"] = _songInfo.CoverUrl; + url = ConnectionBase.ConstructUrlWithParameters("http://service.t.sina.com.cn/share/share.php", parameters); + break; + case Sites.Msn: + parameters["url"] = _songInfo.Url; + parameters["title"] = Text; + parameters["screenshot"] = _songInfo.CoverUrl; + url = ConnectionBase.ConstructUrlWithParameters("http://profile.live.com/badge", parameters); + break; + case Sites.Kaixin: + parameters["rurl"] = _songInfo.Url; + parameters["rcontent"] = ""; + parameters["rtitle"] = Text; + url = ConnectionBase.ConstructUrlWithParameters("http://www.kaixin001.com/repaste/bshare.php", parameters); + break; + case Sites.Renren: + parameters["resourceUrl"] = _songInfo.Url; + parameters["title"] = GetShareTextPartOne(_songInfo.SongName, _songInfo.ArtistName); ; + parameters["pic"] = _songInfo.CoverUrl; + parameters["description"] = GetShareTextPartTwo(_songInfo.ChannelName); + parameters["charset"] = "utf-8"; + url = ConnectionBase.ConstructUrlWithParameters("http://widget.renren.com/dialog/share", parameters); + break; + case Sites.TencentWeibo: + parameters["url"] = _songInfo.Url; + parameters["title"] = Text; + parameters["site"] = "http://www.kfstorm.com/doubanfm"; + parameters["pic"] = _songInfo.CoverUrl; + parameters["appkey"] = "801098586"; + url = ConnectionBase.ConstructUrlWithParameters("http://v.t.qq.com/share/share.php", parameters); + break; + case Sites.Fanfou: + parameters["u"] = _songInfo.Url; + parameters["t"] = Text; + parameters["s"] = "bm"; + url = ConnectionBase.ConstructUrlWithParameters("http://fanfou.com/sharer", parameters); + break; + case Sites.Facebook: + parameters["u"] = _songInfo.Url; + parameters["t"] = Text; + url = ConnectionBase.ConstructUrlWithParameters("http://www.facebook.com/sharer.php", parameters); + break; + case Sites.Twitter: + parameters["status"] = Text + " " + _songInfo.Url; + url = ConnectionBase.ConstructUrlWithParameters("http://twitter.com/home", parameters); + break; + case Sites.Qzone: + parameters["url"] = _songInfo.Url; + parameters["title"] = Text; + url = ConnectionBase.ConstructUrlWithParameters("http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey", parameters); + break; + default: + break; + } + return url; + } + + /// + /// 打开分享链接或复制网址 + /// + public void Go() + { + if (Site == Sites.None) + { + try + { + System.Windows.Clipboard.Clear(); + System.Windows.Clipboard.SetText(Url); + } + catch { } + } + else + { + UrlHelper.OpenLink(GetShareLink()); + } + } + + /// + /// 获取分享文字 + /// + static string GetShareText(string songName, string artistName, string channelName, bool withSource = true) + { + + return GetShareTextPartOne(songName, artistName) + " " + GetShareTextPartTwo(channelName, withSource); + } + + static string GetShareTextPartOne(string songName, string artistName) + { + return string.Format(Resources.Resources.ShareTextPartOne, songName, artistName); + } + + static string GetShareTextPartTwo(string channelName, bool withSource = true) + { + return string.Format(Resources.Resources.ShareTextPartTwo, withSource ? "(http://kfstorm.com/doubanfm)" : string.Empty, channelName); + } + } +} \ No newline at end of file diff --git a/DoubanFM.Core/ShareSongInfo.cs b/DoubanFM.Core/ShareSongInfo.cs new file mode 100644 index 0000000..9bfa771 --- /dev/null +++ b/DoubanFM.Core/ShareSongInfo.cs @@ -0,0 +1,90 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DoubanFM.Core +{ + /// + /// 分享音乐信息 + /// + class ShareSongInfo + { + /// + /// 歌曲标题(或者DJ节目名称) + /// + public string SongName { get; set; } + /// + /// 表演者 + /// + public string ArtistName { get; set; } + /// + /// 频道名称(或者DJ频道名称) + /// + public string ChannelName { get; set; } + /// + /// 分享的电台链接 + /// + public string Url { get; set; } + /// + /// 封面地址 + /// + public string CoverUrl { get; set; } + + /// + /// 生成 class 的新实例。 + /// + /// 歌曲标题(或者DJ节目名称) + /// 表演者 + /// 频道名称(或者DJ频道名称) + /// 分享的电台链接 + /// 封面地址 + internal ShareSongInfo(string songName, string artistName, string channelName, string url, string coverUrl) + { + SongName = songName; + ArtistName = artistName; + ChannelName = channelName; + Url = string.IsNullOrEmpty(url) ? "http://douban.fm" : url; + CoverUrl = coverUrl; + } + + /// + /// 获取分享音乐信息 + /// + /// 歌曲 + /// 频道(或者DJ节目) + /// + internal static ShareSongInfo GetInfo(Song song, Channel channel) + { + string songName = song.Title; + string channelName = channel.Name; ; + string url = null; + Parameters parameters = new Parameters(); + parameters["cid"] = channel.IsRedHeart ? Channel.PersonalId : channel.Id; + if (!song.IsAd) + { + parameters["start"] = song.SongId + "g" + song.SSId + "g" + channel.Id; + //url = "http://douban.fm/?start=" + song.SongId + "g" + song.SSId + "g" + channel.Id + "&cid=" + channel.Id; + } + else + { + parameters["daid"] = song.SongId; + //url = "http://douban.fm/?daid=" + song.SongId + "&cid=" + channel.Id; + } + if (channel.IsSpecial) + { + parameters["context"] = channel.Context; + //url += "&context=" + channel.Context; + } + url = ConnectionBase.ConstructUrlWithParameters("http://douban.fm/", parameters); + + return new ShareSongInfo(songName, song.Artist, channelName, url, song.Picture); + } + } +} diff --git a/DoubanFM.Core/UrlHelper.cs b/DoubanFM.Core/UrlHelper.cs new file mode 100644 index 0000000..730faca --- /dev/null +++ b/DoubanFM.Core/UrlHelper.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DoubanFM.Core +{ + public static class UrlHelper + { + /// + /// 安全地使用默认浏览器打开网页 + /// + /// The URL. + public static void OpenLink(string url) + { + try + { + System.Diagnostics.Process.Start(url); + } + catch (Exception exc1) + { + // System.ComponentModel.Win32Exception is a known exception that occurs when Firefox is default browser. + // It actually opens the browser but STILL throws this exception so we can just ignore it. If not this exception, + // then attempt to open the URL in IE instead. + if (!(exc1 is System.ComponentModel.Win32Exception)) + { + // sometimes throws exception so we have to just ignore + // this is a common .NET bug that no one online really has a great reason for so now we just need to try to open + // the URL using IE if we can. + try + { + System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo("IExplore.exe", url); + System.Diagnostics.Process.Start(startInfo); + startInfo = null; + } + catch (Exception exc2) + { + // still nothing we can do so just show the error to the user here. + System.Windows.MessageBox.Show(exc2.Message); + } + } + } + } + } +} \ No newline at end of file diff --git a/DoubanFM.sln b/DoubanFM.sln new file mode 100644 index 0000000..eb1f97e --- /dev/null +++ b/DoubanFM.sln @@ -0,0 +1,52 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.20623.1 VSUPREVIEW +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DoubanFM", "DoubanFM\DoubanFM.csproj", "{DDDAF282-C866-4036-AAF0-146D6D74080B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DoubanFM.Core", "DoubanFM.Core\DoubanFM.Core.csproj", "{AA75B5E6-F373-49D7-B2E0-16C3E57321F7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NotifyIconWpf", "NotifyIconWpf\NotifyIconWpf.csproj", "{7AC63864-7638-41C4-969C-D3197EF2BED9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{83D9C222-9C9B-4666-AF75-8070323790E5}" + ProjectSection(SolutionItems) = preProject + version.dat = version.dat + WPFSoundVisualizationLib.dll = WPFSoundVisualizationLib.dll + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DoubanFM.Bass", "DoubanFM.Bass\DoubanFM.Bass.csproj", "{62324CFD-03FF-44B4-9204-66BAE86972B6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DwmHelper", "DwmHelper\DwmHelper.csproj", "{368CDBE6-0BA2-4DAD-ACEB-FBB8EEDB1BD7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DDDAF282-C866-4036-AAF0-146D6D74080B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DDDAF282-C866-4036-AAF0-146D6D74080B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DDDAF282-C866-4036-AAF0-146D6D74080B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DDDAF282-C866-4036-AAF0-146D6D74080B}.Release|Any CPU.Build.0 = Release|Any CPU + {AA75B5E6-F373-49D7-B2E0-16C3E57321F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AA75B5E6-F373-49D7-B2E0-16C3E57321F7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AA75B5E6-F373-49D7-B2E0-16C3E57321F7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AA75B5E6-F373-49D7-B2E0-16C3E57321F7}.Release|Any CPU.Build.0 = Release|Any CPU + {7AC63864-7638-41C4-969C-D3197EF2BED9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7AC63864-7638-41C4-969C-D3197EF2BED9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7AC63864-7638-41C4-969C-D3197EF2BED9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7AC63864-7638-41C4-969C-D3197EF2BED9}.Release|Any CPU.Build.0 = Release|Any CPU + {62324CFD-03FF-44B4-9204-66BAE86972B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {62324CFD-03FF-44B4-9204-66BAE86972B6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {62324CFD-03FF-44B4-9204-66BAE86972B6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {62324CFD-03FF-44B4-9204-66BAE86972B6}.Release|Any CPU.Build.0 = Release|Any CPU + {368CDBE6-0BA2-4DAD-ACEB-FBB8EEDB1BD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {368CDBE6-0BA2-4DAD-ACEB-FBB8EEDB1BD7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {368CDBE6-0BA2-4DAD-ACEB-FBB8EEDB1BD7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {368CDBE6-0BA2-4DAD-ACEB-FBB8EEDB1BD7}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/DoubanFM/App.xaml b/DoubanFM/App.xaml new file mode 100644 index 0000000..1a4ca56 --- /dev/null +++ b/DoubanFM/App.xaml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/DoubanFM/App.xaml.cs b/DoubanFM/App.xaml.cs new file mode 100644 index 0000000..42d4b89 --- /dev/null +++ b/DoubanFM/App.xaml.cs @@ -0,0 +1,369 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using DoubanFM.Core; +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Deployment.Application; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.IO.MemoryMappedFiles; +using System.Linq; +using System.Runtime.Serialization.Formatters.Binary; +using System.Text; +using System.Threading; +using System.Windows; +using System.Windows.Markup; + +namespace DoubanFM +{ + /// + /// App.xaml 的交互逻辑 + /// + public partial class App : Application + { + private Mutex mutex; + private static object exceptionObject = null; + + /// + /// 启动时的时间 + /// + public static DateTime StartTime { get; set; } + + /// + /// 是否已启动 + /// + public static bool Started { get; set; } + + static App() + { + Started = false; + + try + { + AppVersion = ApplicationDeployment.CurrentDeployment.CurrentVersion; + } + catch (Exception ex) + { + Debug.WriteLine(ex.Message); + try + { + var exePath = System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0].FullyQualifiedName; + var versionPath = Path.Combine(Path.GetDirectoryName(exePath), "version.dat"); + AppVersion = Version.Parse(File.ReadAllText(versionPath)); + } + catch (Exception ex2) + { + Debug.WriteLine(ex2.Message); + AppVersion = typeof (App).Assembly.GetName().Version; + } + } + } + + public App() + { + //只允许运行一个实例 + bool createdNew = false; + mutex = new Mutex(true, "{DBFE3F28-BA77-4FF6-9EBF-4FED90151A3E}", out createdNew); + if (!createdNew) + { + Channel channel = Channel.FromCommandLineArgs(System.Environment.GetCommandLineArgs().ToList()); + try + { + if (channel != null) + { + WriteStringToMappedFile(channel.ToCommandLineArgs()); + } + else + { + WriteStringToMappedFile("-show"); + } + } + catch { } + Debug.WriteLine("检测到已有一个豆瓣电台在运行,程序将关闭"); + Shutdown(0); + return; + } + + //设置调试输出 + Debug.AutoFlush = true; + Debug.Listeners.Add(new TextWriterTraceListener("DoubanFM.log")); + + Debug.WriteLine(string.Empty); + Debug.WriteLine("**********************************************************************"); + Debug.WriteLine("豆瓣电台启动时间:" + App.GetPreciseTime(DateTime.Now)); + Debug.WriteLine("**********************************************************************"); + Debug.WriteLine(string.Empty); + + //出现未处理的异常时,弹出错误报告窗口,让用户发送错误报告 + AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler((sender, e) => + { + if (mutex != null) + { + mutex.Close(); + mutex = null; + } + if (exceptionObject == null) + { + exceptionObject = e.ExceptionObject; + Debug.WriteLine("**********************************************************************"); + Debug.WriteLine("豆瓣电台出现错误:" + App.GetPreciseTime(DateTime.Now)); + Debug.WriteLine("**********************************************************************"); + Debug.WriteLine(e.ExceptionObject.ToString()); + + try + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine(DateTime.Now.ToString()); + sb.AppendLine(ExceptionWindow.GetSystemInformation()); + sb.AppendLine(ExceptionWindow.GetExceptionMessage(exceptionObject)); + + string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"K.F.Storm\豆瓣电台\error.log"); + string directory = Path.GetDirectoryName(path); + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + File.WriteAllText(path, sb.ToString()); + + DeleteSettingsIfEmergant(); + } + catch { } + + Dispatcher.Invoke(new Action(() => + { + try + { + SaveSettings(); + var mainWindow = MainWindow as DoubanFMWindow; + if (mainWindow != null) + { + if (mainWindow.NotifyIcon != null) mainWindow.NotifyIcon.Dispose(); + } + var window = new ExceptionWindow(); + window.ExceptionObject = exceptionObject; + window.ShowDialog(); + Process.GetCurrentProcess().Kill(); + } + catch + { + SendReport(); + } + })); + } + else + { + DeleteSettingsIfEmergant(); + SendReport(); + } + }); + + Exit += new ExitEventHandler((sender, e) => + { + if (mutex != null) + { + mutex.Close(); + mutex = null; + } + Debug.WriteLine(App.GetPreciseTime(DateTime.Now) + " 程序结束,返回代码为" + e.ApplicationExitCode); + }); + + InitializeComponent(); + + var player = FindResource("Player") as Player; + if (player.Settings.CultureInfo != null) + { + Thread.CurrentThread.CurrentCulture = player.Settings.CultureInfo; + Thread.CurrentThread.CurrentUICulture = player.Settings.CultureInfo; + } + + //System.Windows.Media.RenderOptions.ProcessRenderMode = System.Windows.Interop.RenderMode.SoftwareOnly; + + /* 这句话可以使Global User Interface这个默认的组合字体按当前系统的区域信息选择合适的字形。 + * 只对FrameworkElement有效。对于FlowDocument,由于是从FrameworkContentElement继承, + * 而且FrameworkContentElement.LanguageProperty.OverrideMetadata()无法再次执行, + * 目前我知道的最好的办法是在使用了FlowDocument的XAML的根元素上加上xml:lang="zh-CN", + * 这样就能强制Global User Interface在FlowDocument上使用大陆的字形。 + * */ + FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement), new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.Name))); + } + + protected override void OnSessionEnding(SessionEndingCancelEventArgs e) + { + SaveSettings(); + base.OnSessionEnding(e); + } + + /// + /// 获取时间的一个精确表示 + /// + /// 时间 + /// 一个精确表示 + public static string GetPreciseTime(DateTime time) + { + return time.ToString() + " " + time.Millisecond + "ms"; + } + + /// + /// 内存映射文件的文件名 + /// + public static string _mappedFileName = "{04EFCEB4-F10A-403D-9824-1E685C4B7961}"; + + /// + /// 将字符串写入内存映射文件 + /// + internal static void WriteStringToMappedFile(string content) + { + using (MemoryMappedFile mappedFile = MemoryMappedFile.OpenExisting(_mappedFileName)) + { + using (Stream stream = mappedFile.CreateViewStream()) + { + using (StreamWriter writer = new StreamWriter(stream)) + { + writer.WriteLine(content); + } + } + } + } + + /// + /// 从内存映射文件中读入字符串 + /// + internal static string ReadStringFromMappedFile() + { + using (MemoryMappedFile mappedFile = MemoryMappedFile.OpenExisting(_mappedFileName)) + { + using (Stream stream = mappedFile.CreateViewStream()) + { + using (StreamReader reader = new StreamReader(stream)) + { + return reader.ReadLine(); + } + } + } + } + + /// + /// 清除内存映射文件 + /// + internal static void ClearMappedFile() + { + using (MemoryMappedFile mappedFile = MemoryMappedFile.OpenExisting(_mappedFileName)) + { + using (Stream stream = mappedFile.CreateViewStream()) + { + using (StreamWriter writer = new StreamWriter(stream)) + { + writer.WriteLine(""); + } + } + } + } + + private void SendReport() + { + if (exceptionObject != null) + { + lock (exceptionObject) + { + try + { + string exceptionMessage = ExceptionWindow.GetExceptionMessage(exceptionObject); + string userMessage = string.Empty; + string systemInformation = ExceptionWindow.GetSystemInformation(); +#if DEBUG || TEST + Debug.WriteLine(systemInformation); + Debug.WriteLine(exceptionMessage); +#else + ExceptionWindow.SendReport(exceptionMessage, userMessage, systemInformation); +#endif + } + catch { } + Process.GetCurrentProcess().Kill(); + } + } + } + + /// + /// 删除所有设置 + /// + public static void DeleteSettings(bool useLock = true) + { + if (useLock && exceptionObject != null) + { +#if !DEBUG + lock (exceptionObject) + { + DeleteSettings(false); + } +#endif + } + else + { + try + { + var dataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"K.F.Storm\豆瓣电台"); + if (!Directory.Exists(dataFolder)) return; + var files = Directory.GetFiles(dataFolder, "*.dat"); + foreach (var file in files) + { + File.Delete(file); + } + } + catch (Exception ex) + { + Debug.WriteLine((ex.ToString())); + } + } + } + + private static bool _neverSaveSettings = false; + + /// + /// 如果软件无法正常启动,则删除设置 + /// + public static void DeleteSettingsIfEmergant() + { +#if !DEBUG + if (Started && DateTime.Now - StartTime >= TimeSpan.FromSeconds(5)) return; + NeverSaveSettings(); + DeleteSettings(); +#endif + } + + /// + /// 保存设置 + /// + /// 软件的主窗口 + public void SaveSettings(DoubanFMWindow mainWindow = null) + { + if (_neverSaveSettings) return; + if (mainWindow == null) + { + mainWindow = MainWindow as DoubanFMWindow; + } + if (mainWindow == null) return; + + var player = FindResource("Player") as Player; + if (player != null) player.SaveSettings(); + if (mainWindow._lyricsSetting != null) mainWindow._lyricsSetting.Save(); + if (mainWindow.ShareSetting != null) mainWindow.ShareSetting.Save(); + if (mainWindow.HotKeys != null) mainWindow.HotKeys.Save(); + } + + /// + /// 本次运行不再保存设置 + /// + public static void NeverSaveSettings() + { + _neverSaveSettings = true; + } + + public static Version AppVersion { get; private set; } + } +} \ No newline at end of file diff --git a/DoubanFM/AppCommand.cs b/DoubanFM/AppCommand.cs new file mode 100644 index 0000000..0fbd34d --- /dev/null +++ b/DoubanFM/AppCommand.cs @@ -0,0 +1,248 @@ +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; +using System.Windows; +using System.Windows.Interop; + +namespace DoubanFM +{ + public class AppCommand : IDisposable + { + public class AppCommandEventArgs : EventArgs + { + public Command Command { get; private set; } + public Device Device { get; private set; } + public Keys Keys { get; private set; } + public bool Handled { get; set; } + + public AppCommandEventArgs(Command command, Device device, Keys keys) + { + Command = command; + Device = device; + Keys = keys; + } + } + + public delegate void AppCommndEventhandler(object sender, AppCommandEventArgs e); + + public event AppCommndEventhandler Fire; + + protected virtual void OnFire(AppCommandEventArgs e) + { + AppCommndEventhandler handler = Fire; + if (handler != null) handler(this, e); + } + + [DllImport("user32.dll", SetLastError = true)] + private static extern bool RegisterShellHookWindow(IntPtr hWnd); + + [DllImport("user32.dll", SetLastError = true)] + private static extern bool DeregisterShellHookWindow(IntPtr hWnd); + + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] + private static extern uint RegisterWindowMessage(string lpString); + + private static int WM_SHELLHOOKMESSAGE; + private static readonly IntPtr HSHELL_APPCOMMAND = new IntPtr(12); + private const uint FAPPCOMMAND_MASK = 0xF000; + + private IntPtr hWnd; + private HwndSource source; + private bool disposed = false; + + public AppCommand(IntPtr hWnd) + { + this.hWnd = hWnd; + } + + public AppCommand(Window window) + : this(new WindowInteropHelper(window).EnsureHandle()) + { + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (!disposed) + { + if (disposing) + { + } + + Stop(); + hWnd = IntPtr.Zero; + + disposed = true; + + } + } + + ~AppCommand() + { + Dispose(false); + } + + + public void Start() + { + if (disposed) + { + throw new ObjectDisposedException(null); + } + + if (source == null) + { + source = HwndSource.FromHwnd(hWnd); + if (source == null) + { + throw new InvalidOperationException("hWnd is invalid."); + } + source.AddHook(WndProc); + WM_SHELLHOOKMESSAGE = (int) RegisterWindowMessage("SHELLHOOK"); + if (WM_SHELLHOOKMESSAGE == 0) + { + int error = Marshal.GetLastWin32Error(); + throw new Win32Exception(error, "Register window message 'SHELLHOOK' failed."); + } + if (!RegisterShellHookWindow(hWnd)) + { + int error = Marshal.GetLastWin32Error(); + throw new Win32Exception(error, "Call RegisterShellHookWindow failed."); + } + } + } + + private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + { + if (msg == WM_SHELLHOOKMESSAGE && wParam == HSHELL_APPCOMMAND) + { + var command = GetAppCommandLParam(lParam); + var device = GetDeviceLParam(lParam); + var keys = GetKeyStateLParam(lParam); + + var e = new AppCommandEventArgs(command, device, keys); + OnFire(e); + handled = e.Handled; + } + return IntPtr.Zero; + } + + protected static Command GetAppCommandLParam(IntPtr lParam) + { + return (Command) ((short) (((ushort) ((((uint) lParam.ToInt64()) >> 16) & 0xffff)) & ~FAPPCOMMAND_MASK)); + } + + protected static Device GetDeviceLParam(IntPtr lParam) + { + return (Device) ((ushort) (((ushort) ((((uint) lParam.ToInt64()) >> 16) & 0xffff)) & FAPPCOMMAND_MASK)); + } + + protected static Keys GetKeyStateLParam(IntPtr lParam) + { + return (Keys) ((ushort) (((uint) lParam.ToInt64()) & 0xffff)); + } + + public void Stop() + { + if (disposed) + { + throw new ObjectDisposedException(null); + } + + if (source != null) + { + source.RemoveHook(WndProc); + if (!source.IsDisposed) + { + if (!DeregisterShellHookWindow(hWnd)) + { + int error = Marshal.GetLastWin32Error(); + throw new Win32Exception(error, "Call DeregisterShellHookWindow failed."); + } + source.Dispose(); + } + source = null; + } + } + + public enum Command + { + APPCOMMAND_BASS_BOOST = 20, + APPCOMMAND_BASS_DOWN = 19, + APPCOMMAND_BASS_UP = 21, + APPCOMMAND_BROWSER_BACKWARD = 1, + APPCOMMAND_BROWSER_FAVORITES = 6, + APPCOMMAND_BROWSER_FORWARD = 2, + APPCOMMAND_BROWSER_HOME = 7, + APPCOMMAND_BROWSER_REFRESH = 3, + APPCOMMAND_BROWSER_SEARCH = 5, + APPCOMMAND_BROWSER_STOP = 4, + APPCOMMAND_CLOSE = 31, + APPCOMMAND_COPY = 36, + APPCOMMAND_CORRECTION_LIST = 45, + APPCOMMAND_CUT = 37, + APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE = 43, + APPCOMMAND_FIND = 28, + APPCOMMAND_FORWARD_MAIL = 40, + APPCOMMAND_HELP = 27, + APPCOMMAND_LAUNCH_APP1 = 17, + APPCOMMAND_LAUNCH_APP2 = 18, + APPCOMMAND_LAUNCH_MAIL = 15, + APPCOMMAND_LAUNCH_MEDIA_SELECT = 16, + APPCOMMAND_MEDIA_CHANNEL_DOWN = 52, + APPCOMMAND_MEDIA_CHANNEL_UP = 51, + APPCOMMAND_MEDIA_FAST_FORWARD = 49, + APPCOMMAND_MEDIA_NEXTTRACK = 11, + APPCOMMAND_MEDIA_PAUSE = 47, + APPCOMMAND_MEDIA_PLAY = 46, + APPCOMMAND_MEDIA_PLAY_PAUSE = 14, + APPCOMMAND_MEDIA_PREVIOUSTRACK = 12, + APPCOMMAND_MEDIA_RECORD = 48, + APPCOMMAND_MEDIA_REWIND = 50, + APPCOMMAND_MEDIA_STOP = 13, + APPCOMMAND_MIC_ON_OFF_TOGGLE = 44, + APPCOMMAND_MICROPHONE_VOLUME_DOWN = 25, + APPCOMMAND_MICROPHONE_VOLUME_MUTE = 24, + APPCOMMAND_MICROPHONE_VOLUME_UP = 26, + APPCOMMAND_NEW = 29, + APPCOMMAND_OPEN = 30, + APPCOMMAND_PASTE = 38, + APPCOMMAND_PRINT = 33, + APPCOMMAND_REDO = 35, + APPCOMMAND_REPLY_TO_MAIL = 39, + APPCOMMAND_SAVE = 32, + APPCOMMAND_SEND_MAIL = 41, + APPCOMMAND_SPELL_CHECK = 42, + APPCOMMAND_TREBLE_DOWN = 22, + APPCOMMAND_TREBLE_UP = 23, + APPCOMMAND_UNDO = 34, + APPCOMMAND_VOLUME_DOWN = 9, + APPCOMMAND_VOLUME_MUTE = 8, + APPCOMMAND_VOLUME_UP = 10 + } + + public enum Device + { + FAPPCOMMAND_KEY = 0, + FAPPCOMMAND_MOUSE = 0x8000, + FAPPCOMMAND_OEM = 0x1000 + } + + [Flags] + public enum Keys + { + MK_CONTROL = 0x0008, + MK_LBUTTON = 0x0001, + MK_MBUTTON = 0x0010, + MK_RBUTTON = 0x0002, + MK_SHIFT = 0x0004, + MK_XBUTTON1 = 0x0020, + MK_XBUTTON2 = 0x0040 + } + } +} \ No newline at end of file diff --git a/DoubanFM/ChildWindowBase.cs b/DoubanFM/ChildWindowBase.cs new file mode 100644 index 0000000..dd362ff --- /dev/null +++ b/DoubanFM/ChildWindowBase.cs @@ -0,0 +1,78 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; + +namespace DoubanFM +{ + /// + /// DouanFMWindow的子窗口基类 + /// + [TemplatePart(Name = "PART_Close", Type = typeof(Button))] + public class ChildWindowBase : WindowBase + { + static ChildWindowBase() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(ChildWindowBase), new FrameworkPropertyMetadata(typeof(ChildWindowBase))); + } + + public ChildWindowBase() + { + try + { + Owner = Application.Current.MainWindow; + AllowsTransparency = Owner.AllowsTransparency; + this.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner; + } + catch { } + } + + protected override void OnInitialized(EventArgs e) + { + base.OnInitialized(e); + + if (Owner != null) + { + System.Windows.Data.Binding binding = new System.Windows.Data.Binding("Background"); + binding.Source = Owner; + this.SetBinding(Window.BackgroundProperty, binding); + } + } + + protected override void OnClosing(System.ComponentModel.CancelEventArgs e) + { + if (Owner != null) + { + Owner.Activate(); + } + + base.OnClosing(e); + } + + private Button btnClose; + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + btnClose = this.Template.FindName("PART_Close", this) as Button; + if (btnClose != null) + { + btnClose.Click += new RoutedEventHandler(btnClose_Click); + } + } + + private void btnClose_Click(object sender, RoutedEventArgs e) + { + this.Close(); + } + } +} \ No newline at end of file diff --git a/DoubanFM/ColorFunctions.cs b/DoubanFM/ColorFunctions.cs new file mode 100644 index 0000000..be996a0 --- /dev/null +++ b/DoubanFM/ColorFunctions.cs @@ -0,0 +1,616 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System.Configuration; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System; +using System.Threading; +namespace DoubanFM +{ + /// + /// 有关颜色的方法类 + /// 主要用于计算窗口背景 + /// + public class ColorFunctions + { + /// + /// 两种颜色不同的阀值 + /// + public readonly static double CoverColorDiff = double.Parse(ConfigurationManager.AppSettings["ColorFunctions.CoverColorDiff"]); + /// + /// 亮度调整幅度 + /// + public readonly static double ReviseParameter = double.Parse(ConfigurationManager.AppSettings["ColorFunctions.ReviseParameter"]); + /// + /// 用于调整封面右边取色区域的大小,具体表示右边区域宽度占图片宽度的百分比 + /// + public readonly static double RightSideWidth = double.Parse(ConfigurationManager.AppSettings["ColorFunctions.RightSideWidth"]); + /// + /// 判断颜色是否太暗 + /// + public readonly static double TooDark = double.Parse(ConfigurationManager.AppSettings["ColorFunctions.TooDark"]); + /// + /// 判断颜色是否太暗亮 + /// + public readonly static double TooBright = double.Parse(ConfigurationManager.AppSettings["ColorFunctions.TooBright"]); + /// + /// 色相偏移 + /// + public readonly static double HueOffset = double.Parse(ConfigurationManager.AppSettings["ColorFunctions.HueOffset"]); + /// + /// 进度条颜色调整参数 + /// + public readonly static double ProgressBarReviseParameter = double.Parse(ConfigurationManager.AppSettings["ColorFunctions.ProgressBarReviseParameter"]); + /// + /// 判断颜色饱和度是否太低 + /// + public readonly static double NotSaturateEnough = double.Parse(ConfigurationManager.AppSettings["ColorFunctions.NotSaturateEnough"]); + /// + /// 判断颜色饱和度是否接近0 + /// + public readonly static double AlmostZeroSaturation = double.Parse(ConfigurationManager.AppSettings["ColorFunctions.AlmostZeroSaturation"]); + /// + /// 计算图片平均色时是否使用颜色的饱和度作权重 + /// + public readonly static bool EnableColorWeight = bool.Parse(ConfigurationManager.AppSettings["ColorFunctions.EnableColorWeight"]); + + /// + /// 人脸的颜色 + /// + public static readonly Color FaceColor = + (Color)ColorConverter.ConvertFromString(ConfigurationManager.AppSettings["ColorFunctions.FaceColor"]); + + /// + /// 人脸色0权重的颜色差异阈值 + /// + public static readonly double ZeroWeightFaceColorDifference = + double.Parse(ConfigurationManager.AppSettings["ColorFunctions.ZeroWeightFaceColorDifference"]); + + /// + /// 最低权重 + /// + public static readonly double MinWeight = + double.Parse(ConfigurationManager.AppSettings["ColorFunctions.MinWeight"]); + + public delegate void ComputeCompleteCallback(Color color); + + /// + /// 异步从图片中获取背景颜色 + /// + /// 图片 + /// 计算完成后调用的委托 + public static void GetImageColorForBackgroundAsync(BitmapSource image, ComputeCompleteCallback callback) + { + FormatConvertedBitmap bitmap = null; + bool isFrozen = image.IsFrozen; + if (!isFrozen) + { + //由于image没有冻结,所以image不能跨线程使用,这时要在当前线程中将image转换为另一个位图 + bitmap = new FormatConvertedBitmap(image, PixelFormats.Rgb24, BitmapPalettes.WebPalette, 0); + } + ThreadPool.QueueUserWorkItem(state => + { + if (isFrozen) + { + //由于image已经冻结,所以image可以跨线程使用,这时在新线程中将image转换为另一个位图 + bitmap = new FormatConvertedBitmap(image, PixelFormats.Rgb24, BitmapPalettes.WebPalette, 0); + } + callback(GetImageColorForBackground(bitmap)); + }); + } + + /// + /// 从图片中获取背景颜色 + /// + /// 图片 + public static Color GetImageColorForBackground(FormatConvertedBitmap bitmap) + { + const int bytesPerPixel = 3; + + if (bitmap.CanFreeze) bitmap.Freeze(); + var pixels = new byte[bitmap.PixelHeight * bitmap.PixelWidth * bytesPerPixel]; + bitmap.CopyPixels(pixels, bitmap.PixelWidth * bytesPerPixel, 0); + var width = bitmap.PixelWidth; + var height = bitmap.PixelHeight; + + //计算颜色的均值 + Color color = GetColorOfRegion(pixels, width, height, 0, width, 0, height); + + var hsl = new HslColor(color); + if (IsNotSaturateEnough(hsl) && !IsAlmostZeroSaturation(hsl)) + hsl.Saturation += 0.2; + + return Revise(hsl).ToRgb(); + } + + /// + /// 从图片中获取指定区域的背景颜色 + /// + /// The pixels. + /// The width. + /// The height. + /// The left. + /// The right. + /// The top. + /// The bottom. + /// if set to true [force disable color weight]. + /// + public static Color GetColorOfRegion(byte[] pixels, int width, int height, int left, int right, int top, + int bottom, bool forceDisableColorWeight = false, bool removeFaceColor = true) + { + const int bytesPerPixel = 3; + double sr = 0, sg = 0, sb = 0; + double totalweight = 0; + for (int i = top; i < bottom; i++) + { + for (int j = left; j < right; j++) + { + byte r = pixels[(i * width + j) * bytesPerPixel + 0]; + byte g = pixels[(i * width + j) * bytesPerPixel + 1]; + byte b = pixels[(i * width + j) * bytesPerPixel + 2]; + double weight; + if (!forceDisableColorWeight && EnableColorWeight) + { + var color = Color.FromRgb(r, g, b); + var hslColor = new HslColor(color); + weight = (1 - Math.Abs(1 - 2*hslColor.Lightness))*hslColor.Saturation; + if (weight < MinWeight) + { + weight = 0; + } + if (removeFaceColor) + { + var difference = Math.Abs(new HslColor(FaceColor).Hue - hslColor.Hue)/360; + if (difference <= ZeroWeightFaceColorDifference) + { + weight = 0; + } + else + { + weight = weight*difference; + } + } + } + else + { + weight = 1; + } + totalweight += weight; + sr += r * weight; + sg += g * weight; + sb += b * weight; + } + } + + if (totalweight <= 0) + { + if (removeFaceColor) + { + //当去除人脸色彩后总权重为0时,禁用去除人脸色彩 + return GetColorOfRegion(pixels, width, height, left, right, top, bottom, false, false); + } + else + { + //纯灰度图片不能使用权重 + var newColor = GetColorOfRegion(pixels, width, height, left, right, top, bottom, true); + var newHslColor = new HslColor(newColor); + newHslColor.Saturation = 0; + return newHslColor.ToRgb(); + } + } + else + { + sr = sr/totalweight; + sg = sg/totalweight; + sb = sb/totalweight; + return Color.FromRgb((byte) sr, (byte) sg, (byte) sb); + } + } + /// + /// 两种颜色差异是否足够大 + /// + /// 颜色1 + /// 颜色2 + /// Boolean值 + public static bool IsTooMuchDiff(HslColor c1, HslColor c2) + { + return Difference(c1, c2) > CoverColorDiff; + //return Math.Abs((c1.R - c2.R) * (c1.R - c2.R) + (c1.G - c2.G) * (c1.G - c2.G) + (c1.B - c2.B) * (c1.B - c2.B)) > CoverColorDiff; + } + /// + /// 计算两种颜色的差异。0为无差异,1为差异最大值 + /// + /// 颜色1 + /// 颜色2 + /// 差异值 + public static double Difference(HslColor c1, HslColor c2) + { + return Difference(c1.ToRgb(), c2.ToRgb()); + } + + /// + /// 计算两种颜色的差异。0为无差异,1为差异最大值 + /// + /// 颜色1 + /// 颜色2 + /// 是否比较Alpha通道 + /// + /// 差异值 + /// + public static double Difference(Color c1, Color c2, bool compareAlpha = true) + { + if (compareAlpha) + { + return + Math.Sqrt((Math.Pow(c1.A - c2.A, 2) + Math.Pow(c1.R - c2.R, 2) + Math.Pow(c1.G - c2.G, 2) + + Math.Pow(c1.B - c2.B, 2))/4/255/255); + } + return Math.Sqrt((Math.Pow(c1.R - c2.R, 2) + Math.Pow(c1.G - c2.G, 2) + Math.Pow(c1.B - c2.B, 2))/3/255/255); + } + + /// + /// 颜色饱和度是否太低 + /// + /// 颜色 + /// Boolean值 + public static bool IsNotSaturateEnough(HslColor color) + { + return color.Saturation < NotSaturateEnough; + } + /// + /// 颜色饱和度是否接近0 + /// + /// 颜色 + /// Boolean值 + public static bool IsAlmostZeroSaturation(HslColor color) + { + return color.Saturation < AlmostZeroSaturation; + } + /// + /// 颜色是否太暗 + /// + /// 颜色 + /// Boolean值 + public static bool IsTooDark(HslColor color) + { + return color.Lightness < TooDark; + } + /// + /// 颜色是否太亮 + /// + /// 颜色 + /// Boolean值 + public static bool IsTooBright(HslColor color) + { + return color.Lightness > TooBright; + } + /// + /// 反色 + /// + /// 原色 + /// 反色 + public static HslColor Reverse(HslColor color) + { + Color rgb = color.ToRgb(); + return new HslColor(Color.FromArgb(rgb.A, (byte)(255 - rgb.R), (byte)(255 - rgb.G), (byte)(255 - rgb.B))); + //return new HSLColor(hsvColor.Alpha, hsvColor.Hue + 180, 1 - hsvColor.Saturation, 1 - hsvColor.Lightness); + } + /// + /// 颜色修正 + /// + /// 待修正色 + /// 参照色 + /// 修正色 + public static HslColor Revise(HslColor color1, HslColor color2) + { + var newcolor = new HslColor(color1.ToRgb()); + while (IsTooBright(newcolor) || !IsTooMuchDiff(newcolor, color2) && !IsTooDark(newcolor) && newcolor.Lightness > 0) + newcolor = ReviseDarker(newcolor); + if (!IsTooDark(newcolor)) return newcolor; + newcolor = ReviseBrighter(color1); + while (IsTooDark(newcolor) || !IsTooMuchDiff(newcolor, color2) && !IsTooBright(newcolor) && newcolor.Lightness < 1) + newcolor = ReviseBrighter(newcolor); + if (!IsTooBright(newcolor)) return newcolor; + if (IsTooBright(color1)) + return ReviseVeryBright(color1); + if (IsTooDark(color1)) + return ReviseVeryDark(color1); + return color1; + + } + /// + /// 无参照色时的颜色修正 + /// + /// 待修正色 + /// 修正色 + public static HslColor Revise(HslColor color) + { + if (IsTooDark(color)) + return ReviseBrighter(color); + if (IsTooBright(color)) + return ReviseVeryBright(color); + //color = ReviseDarker(color); + //if (IsTooDark(color)) + //return ReviseVeryDark(color); + return color; + } + /// + /// 将颜色调整到能够接受的最高亮度 + /// + /// 待修正色 + /// 修正色 + public static HslColor ReviseVeryBright(HslColor color) + { + return ReviseBrighter(color, TooBright - color.Lightness); + } + /// + /// 将颜色调整到能够接受的最低亮度 + /// + /// 待修正色 + /// 修正色 + public static HslColor ReviseVeryDark(HslColor color) + { + return ReviseDarker(color, color.Lightness - TooDark); + } + /// + /// 将颜色调亮特定亮度 + /// + /// 待修正色 + /// 调整的亮度 + /// 修正色 + public static HslColor ReviseBrighter(HslColor color, double brigher) + { + return new HslColor(color.Alpha, color.Hue, color.Saturation, color.Lightness + brigher); + //return Color.FromRgb(ReviseByteBigger(hsvColor.R), ReviseByteBigger(hsvColor.G), ReviseByteBigger(hsvColor.B)); + } + /// + /// 将颜色调亮一些 + /// + /// 待修正色 + /// 修正色 + public static HslColor ReviseBrighter(HslColor color) + { + return ReviseBrighter(color, ReviseParameter); + } + /// + /// 将颜色调暗特定亮度 + /// + /// 待修正色 + /// 调整的亮度 + /// 修正色 + public static HslColor ReviseDarker(HslColor color, double darker) + { + return new HslColor(color.Alpha, color.Hue, color.Saturation, color.Lightness - darker); + } + /// + /// 将颜色调暗一些 + /// + /// 待修正色 + /// 修正色 + public static HslColor ReviseDarker(HslColor color) + { + return ReviseDarker(color, ReviseParameter); + } + } + /// + /// HSL色彩空间的颜色类 + /// + public class HslColor + { + public double a, h, s, l; + + + /// + /// 不透明度。范围:0~1,1为不透明,0为透明 + /// + public double Alpha + { + get + { + return a; + } + set + { + if (value > 1) + a = 1; + else if (value < 0) + a = 0; + else a = value; + } + } + + /// + /// 色相。范围:0~359.9999999。特殊颜色:红:0 黄:60 绿:120 青:180 蓝:240 洋红:300 + /// + public double Hue + { + get + { + return h; + } + set + { + if (value >= 360) + h = value % 360; + else if (value < 0) + h = value - Math.Floor(value / 360) * 360; + else h = value; + } + } + /// + /// 饱和度。范围:0~1。亮度0.5时,0为灰色,1为彩色 + /// + public double Saturation + { + get + { + return s; + } + set + { + if (value > 1) + s = 1; + else if (value < 0) + s = 0; + else s = value; + } + } + + /// + /// 亮度。范围:0~1。0为黑色,0.5为彩色,1为白色 + /// + public double Lightness + { + get + { + return l; + } + set + { + if (value > 1) + l = 1; + else if (value < 0) + l = 0; + else l = value; + } + } + + /// + /// 无参构造函数 + /// + public HslColor() + : this(1, 0, 0, 0) + { + } + /// + /// HSL构造函数 + /// + /// 色相 + /// 饱和度 + /// 亮度 + public HslColor(double hue, double saturation, double lightness) + : this(1, hue, saturation, lightness) + { + } + /// + /// AHSL构造函数 + /// + /// Alpha通道 + /// 色相 + /// 饱和度 + /// 亮度 + public HslColor(double alpha, double hue, double saturation, double lightness) + { + Alpha = alpha; + Hue = hue; + Saturation = saturation; + Lightness = lightness; + } + /// + /// 由RGB颜色类Color构造一个HSLColor的实例 + /// + /// RGB颜色 + public HslColor(Color color) + { + FromRgb(color); + } + /// + /// RGB色彩空间转换 + /// + /// RGB颜色 + public void FromRgb(Color color) + { + a = (double)color.A / 255; + double r = (double)color.R / 255; + double g = (double)color.G / 255; + double b = (double)color.B / 255; + + double min = Math.Min(r, Math.Min(g, b)); + double max = Math.Max(r, Math.Max(g, b)); + double distance = max - min; + + l = (max + min) / 2; + s = 0; + if (distance > 0) + { + s = l < 0.5 ? distance / (max + min) : distance / ((2 - max) - min); + double tempR = (((max - r) / 6) + (distance / 2)) / distance; + double tempG = (((max - g) / 6) + (distance / 2)) / distance; + double tempB = (((max - b) / 6) + (distance / 2)) / distance; + double hT; + if (r == max) + hT = tempB - tempG; + else if (g == max) + hT = (1.0 / 3 + tempR) - tempB; + else + hT = (2.0 / 3 + tempG) - tempR; + if (hT < 0) + hT += 1; + if (hT > 1) + hT -= 1; + h = hT * 360; + } + } + /// + /// 转换到RGB色彩空间 + /// + /// HSL颜色 + /// 转换后的RGB颜色 + public static Color ToRgb(HslColor hsl) + { + byte a = (byte)Math.Round(hsl.Alpha * 255), r, g, b; + if (hsl.Saturation == 0) + { + r = (byte)Math.Round(hsl.Lightness * 255); + g = r; + b = r; + } + else + { + double vH = hsl.Hue / 360; + double v2 = hsl.Lightness < 0.5 ? hsl.Lightness * (1 + hsl.Saturation) : (hsl.Lightness + hsl.Saturation) - (hsl.Lightness * hsl.Saturation); + double v1 = 2 * hsl.Lightness - v2; + r = (byte)Math.Round(255 * HueToRgb(v1, v2, vH + 1.0 / 3)); + g = (byte)Math.Round(255 * HueToRgb(v1, v2, vH)); + b = (byte)Math.Round(255 * HueToRgb(v1, v2, vH - 1.0 / 3)); + } + return Color.FromArgb(a, r, g, b); + } + /// + /// 这个……我也不懂 + /// + /// + /// + /// + /// + public static double HueToRgb(double v1, double v2, double vH) + { + if (vH < 0) vH += 1; + if (vH > 1) vH -= 1; + if (6 * vH < 1) return v1 + ((v2 - v1) * 6 * vH); + if (2 * vH < 1) return v2; + if (3 * vH < 2) return v1 + (v2 - v1) * (2.0 / 3 - vH) * 6; + return v1; + } + /// + /// 转换到RGB色彩空间 + /// + /// RGB颜色 + public Color ToRgb() + { + return ToRgb(this); + } + /// + /// ToString()方法,已重写 + /// + /// ARGB颜色值 + public override string ToString() + { + return ToRgb().ToString(); + } + } +} \ No newline at end of file diff --git a/DoubanFM/ColorPicker/ColorPicker.cs b/DoubanFM/ColorPicker/ColorPicker.cs new file mode 100644 index 0000000..95e9b68 --- /dev/null +++ b/DoubanFM/ColorPicker/ColorPicker.cs @@ -0,0 +1,594 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace DoubanFM +{ + /// + /// 颜色选择器控件 + /// + [TemplatePart(Name = "PART_ColorShadeCanvas", Type = typeof(Canvas))] + [TemplatePart(Name = "PART_ColorShadeSelector", Type = typeof(FrameworkElement))] + [TemplatePart(Name = "PART_ColorSpectrumSlider", Type = typeof(ColorSpectrumSlider))] + [TemplatePart(Name = "PART_TextBoxA", Type = typeof(TextBox))] + [TemplatePart(Name = "PART_TextBoxR", Type = typeof(TextBox))] + [TemplatePart(Name = "PART_TextBoxG", Type = typeof(TextBox))] + [TemplatePart(Name = "PART_TextBoxB", Type = typeof(TextBox))] + [TemplatePart(Name = "PART_TextBoxHexString", Type = typeof(TextBox))] + public class ColorPicker : Control + { + static ColorPicker() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker))); + } + + public ColorPicker() + { + //在控件加载后更新一次颜色 + this.Loaded += (sender, e) => + { + UpdateColor(Color, null); + }; + } + + #region Color属性 + + /// + /// 选择的颜色 + /// + public Color Color + { + get { return (Color)GetValue(ColorProperty); } + set { SetValue(ColorProperty, value); } + } + + public static readonly DependencyProperty ColorProperty = + DependencyProperty.Register("Color", typeof(Color), typeof(ColorPicker), new FrameworkPropertyMetadata(Colors.White, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnColorChanged))); + + public static void OnColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ColorPicker picker = (ColorPicker)d; + + //更新控件的其他属性 + picker.A = picker.Color.A; + picker.R = picker.Color.R; + picker.G = picker.Color.G; + picker.B = picker.Color.B; + if (picker.IsAlphaEnabled) + { + picker.HexString = string.Format("{0:X2}{1:X2}{2:X2}{3:X2}", picker.A, picker.R, picker.G, picker.B); + } + else + { + picker.HexString = string.Format("{0:X2}{1:X2}{2:X2}", picker.R, picker.G, picker.B); + } + + picker.RaiseEvent(new RoutedPropertyChangedEventArgs((Color)e.OldValue, (Color)e.NewValue, ColorChangedEvent)); + + //更新所有TextBox的内容 + picker.ForceUpdateTextBox(); + } + + public event RoutedPropertyChangedEventHandler ColorChanged + { + add + { + AddHandler(ColorChangedEvent, value); + } + remove + { + RemoveHandler(ColorChangedEvent, value); + } + } + + public static readonly RoutedEvent ColorChangedEvent = EventManager.RegisterRoutedEvent("ColorChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler), typeof(ColorPicker)); + + #endregion + + #region A属性 + + /// + /// 颜色的Alpha通道 + /// + public byte A + { + get { return (byte)GetValue(AProperty); } + set { SetValue(AProperty, value); } + } + + public static readonly DependencyProperty AProperty = + DependencyProperty.Register("A", typeof(byte), typeof(ColorPicker), new FrameworkPropertyMetadata((byte)255, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnAChanged))); + + public static void OnAChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ColorPicker picker = (ColorPicker)d; + picker.UpdateColor(Color.FromArgb((byte)e.NewValue, picker.Color.R, picker.Color.G, picker.Color.B), null); + picker.RaiseEvent(new RoutedPropertyChangedEventArgs((byte)e.OldValue, (byte)e.NewValue, AChangedEvent)); + } + + public event RoutedPropertyChangedEventHandler AChanged + { + add + { + AddHandler(AChangedEvent, value); + } + remove + { + RemoveHandler(AChangedEvent, value); + } + } + + public static readonly RoutedEvent AChangedEvent = EventManager.RegisterRoutedEvent("AChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler), typeof(ColorPicker)); + + #endregion + + #region R属性 + + /// + /// 颜色的Red通道 + /// + public byte R + { + get { return (byte)GetValue(RProperty); } + set { SetValue(RProperty, value); } + } + + public static readonly DependencyProperty RProperty = + DependencyProperty.Register("R", typeof(byte), typeof(ColorPicker), new FrameworkPropertyMetadata((byte)255, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnRChanged))); + + public static void OnRChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ColorPicker picker = (ColorPicker)d; + picker.UpdateColor(Color.FromArgb(picker.Color.A, (byte)e.NewValue, picker.Color.G, picker.Color.B), null); + picker.RaiseEvent(new RoutedPropertyChangedEventArgs((byte)e.OldValue, (byte)e.NewValue, RChangedEvent)); + } + + public event RoutedPropertyChangedEventHandler RChanged + { + add + { + AddHandler(RChangedEvent, value); + } + remove + { + RemoveHandler(RChangedEvent, value); + } + } + + public static readonly RoutedEvent RChangedEvent = EventManager.RegisterRoutedEvent("RChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler), typeof(ColorPicker)); + + #endregion + + #region G属性 + + /// + /// 颜色的Green通道 + /// + public byte G + { + get { return (byte)GetValue(GProperty); } + set { SetValue(GProperty, value); } + } + + public static readonly DependencyProperty GProperty = + DependencyProperty.Register("G", typeof(byte), typeof(ColorPicker), new FrameworkPropertyMetadata((byte)255, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnGChanged))); + + public static void OnGChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ColorPicker picker = (ColorPicker)d; + picker.UpdateColor(Color.FromArgb(picker.Color.A, picker.Color.R, (byte)e.NewValue, picker.Color.B), null); + picker.RaiseEvent(new RoutedPropertyChangedEventArgs((byte)e.OldValue, (byte)e.NewValue, GChangedEvent)); + } + + public event RoutedPropertyChangedEventHandler GChanged + { + add + { + AddHandler(GChangedEvent, value); + } + remove + { + RemoveHandler(GChangedEvent, value); + } + } + + public static readonly RoutedEvent GChangedEvent = EventManager.RegisterRoutedEvent("GChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler), typeof(ColorPicker)); + + #endregion + + #region B属性 + + /// + /// 颜色的Blue通道 + /// + public byte B + { + get { return (byte)GetValue(BProperty); } + set { SetValue(BProperty, value); } + } + + public static readonly DependencyProperty BProperty = + DependencyProperty.Register("B", typeof(byte), typeof(ColorPicker), new FrameworkPropertyMetadata((byte)255, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnBChanged))); + + public static void OnBChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ColorPicker picker = (ColorPicker)d; + picker.UpdateColor(Color.FromArgb(picker.Color.A, picker.Color.R, picker.Color.G, (byte)e.NewValue), null); + picker.RaiseEvent(new RoutedPropertyChangedEventArgs((byte)e.OldValue, (byte)e.NewValue, BChangedEvent)); + } + + public event RoutedPropertyChangedEventHandler BChanged + { + add + { + AddHandler(BChangedEvent, value); + } + remove + { + RemoveHandler(BChangedEvent, value); + } + } + + public static readonly RoutedEvent BChangedEvent = EventManager.RegisterRoutedEvent("BChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler), typeof(ColorPicker)); + + #endregion + + #region HexString属性 + + /// + /// 颜色的十六进制字符串表示 + /// + public string HexString + { + get { return (string)GetValue(HexStringProperty); } + set { SetValue(HexStringProperty, value); } + } + + public static readonly DependencyProperty HexStringProperty = + DependencyProperty.Register("HexString", typeof(string), typeof(ColorPicker), new FrameworkPropertyMetadata("FFFFFFFF", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnHexStringChanged)), + new ValidateValueCallback(o => + { + string hex = o as string; + if (hex == null) return false; + if (hex.Length != 8 && hex.Length != 6) return false; + return hex.All(ch => + { + return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f'); + }); + })); + + public static void OnHexStringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ColorPicker picker = (ColorPicker)d; + + if (((string)e.NewValue).Length == 8 && picker.IsAlphaEnabled) + { + picker.UpdateColor(Color.FromArgb( + byte.Parse(((string)e.NewValue).Substring(0, 2), System.Globalization.NumberStyles.HexNumber), + byte.Parse(((string)e.NewValue).Substring(2, 2), System.Globalization.NumberStyles.HexNumber), + byte.Parse(((string)e.NewValue).Substring(4, 2), System.Globalization.NumberStyles.HexNumber), + byte.Parse(((string)e.NewValue).Substring(6, 2), System.Globalization.NumberStyles.HexNumber)), + null); + picker.RaiseEvent(new RoutedPropertyChangedEventArgs((string)e.OldValue, (string)e.NewValue, HexStringChangedEvent)); + } + else if (((string)e.NewValue).Length == 6 && !picker.IsAlphaEnabled) + { + picker.UpdateColor(Color.FromRgb( + byte.Parse(((string)e.NewValue).Substring(0, 2), System.Globalization.NumberStyles.HexNumber), + byte.Parse(((string)e.NewValue).Substring(2, 2), System.Globalization.NumberStyles.HexNumber), + byte.Parse(((string)e.NewValue).Substring(4, 2), System.Globalization.NumberStyles.HexNumber)), + null); + } + } + + public event RoutedPropertyChangedEventHandler HexStringChanged + { + add + { + AddHandler(HexStringChangedEvent, value); + } + remove + { + RemoveHandler(HexStringChangedEvent, value); + } + } + + public static readonly RoutedEvent HexStringChangedEvent = EventManager.RegisterRoutedEvent("HexStringChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler), typeof(ColorPicker)); + + #endregion + + #region IsAlphaEnabled属性 + + /// + /// 颜色中是否包含Alpha通道 + /// + public bool IsAlphaEnabled + { + get { return (bool)GetValue(IsAlphaEnabledProperty); } + set { SetValue(IsAlphaEnabledProperty, value); } + } + + public static readonly DependencyProperty IsAlphaEnabledProperty = + DependencyProperty.Register("IsAlphaEnabled", typeof(bool), typeof(ColorPicker), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnIsAlphaEnabledChanged))); + + public static void OnIsAlphaEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ColorPicker picker = (ColorPicker)d; + if (!(bool)e.NewValue) + { + Color color = picker.Color; + color.A = 255; + picker.HexString = string.Format("{0:X2}{1:X2}{2:X2}", picker.R, picker.G, picker.B); + picker.UpdateColor(color, null); + } + else + { + picker.HexString = string.Format("{0:X2}{1:X2}{2:X2}{3:X2}", picker.A, picker.R, picker.G, picker.B); + } + picker.RaiseEvent(new RoutedPropertyChangedEventArgs((bool)e.OldValue, (bool)e.NewValue, IsAlphaEnabledChangedEvent)); + } + + public event RoutedPropertyChangedEventHandler IsAlphaEnabledChanged + { + add + { + AddHandler(IsAlphaEnabledChangedEvent, value); + } + remove + { + RemoveHandler(IsAlphaEnabledChangedEvent, value); + } + } + + public static readonly RoutedEvent IsAlphaEnabledChangedEvent = EventManager.RegisterRoutedEvent("IsAlphaEnabledChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler), typeof(ColorPicker)); + + #endregion + + #region 字段 + /// + /// 最后一次设置颜色时的精确颜色 + /// + private HsvColor? lastPreciseColor; + /// + /// 指示是否正在更新颜色 + /// + bool updatingColor = false; + + /// + /// 渐变画布 + /// + private Canvas shadeCanvas; + /// + /// 渐变选择器 + /// + private FrameworkElement shadeSelector; + /// + /// 频谱选择器 + /// + private ColorSpectrumSlider spectrumSlider; + /// + /// 代表A值的TextBox + /// + private TextBox tbA; + /// + /// 代表R值的TextBox + /// + private TextBox tbR; + /// + /// 代表G值的TextBox + /// + private TextBox tbG; + /// + /// 代表B值的TextBox + /// + private TextBox tbB; + /// + /// 代表HexString值的TextBox + /// + private TextBox tbHexString; + #endregion + + #region 控件逻辑部分 + + /// + /// 在派生类中重写后,每当应用程序代码或内部进程调用 ,都将调用此方法。 + /// + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + //初始化控件部件 + shadeCanvas = this.Template.FindName("PART_ColorShadeCanvas", this) as Canvas; + shadeSelector = this.Template.FindName("PART_ColorShadeSelector", this) as FrameworkElement; + spectrumSlider = this.Template.FindName("PART_ColorSpectrumSlider", this) as ColorSpectrumSlider; + tbA = this.Template.FindName("PART_TextBoxA", this) as TextBox; + tbR = this.Template.FindName("PART_TextBoxR", this) as TextBox; + tbG = this.Template.FindName("PART_TextBoxG", this) as TextBox; + tbB = this.Template.FindName("PART_TextBoxB", this) as TextBox; + tbHexString = this.Template.FindName("PART_TextBoxHexString", this) as TextBox; + + //为控件部件添加事件处理程序 + shadeCanvas.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(shadeCanvas_PreviewMouseLeftButtonDown); + shadeCanvas.MouseMove += new MouseEventHandler(shadeCanvas_MouseMove); + shadeCanvas.MouseLeftButtonUp += new MouseButtonEventHandler(shadeCanvas_MouseLeftButtonUp); + spectrumSlider.ValueChanged += new RoutedPropertyChangedEventHandler(spectrumSlider_ValueChanged); + + //更新颜色 + UpdateColor(Color, null); + } + + /// + /// 频谱选择器的选择改变时触发 + /// + /// The source of the event. + /// The instance containing the event data. + void spectrumSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) + { + //频谱选择已改变,需更新颜色 + HsvColor hsvColor = lastPreciseColor.HasValue ? lastPreciseColor.Value : HsvColor.FromArgb(Color); + hsvColor.H = spectrumSlider.Value; + UpdateColor(hsvColor.ToArgb(), hsvColor); + } + + /// + /// 渐变选择器中按下鼠标左键时触发 + /// + /// The source of the event. + /// The instance containing the event data. + void shadeCanvas_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + Point p = e.GetPosition(shadeCanvas); + UpdateColorFromPoint(p); + shadeCanvas.CaptureMouse(); + e.Handled = true; + } + + /// + /// 渐变选择器中松开鼠标左键时触发 + /// + /// The source of the event. + /// The instance containing the event data. + void shadeCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) + { + shadeCanvas.ReleaseMouseCapture(); + } + + /// + /// 渐变选择器中移动鼠标时触发 + /// + /// The source of the event. + /// The instance containing the event data. + void shadeCanvas_MouseMove(object sender, MouseEventArgs e) + { + if (shadeCanvas.IsMouseCaptured && e.LeftButton == MouseButtonState.Pressed) + { + Point p = e.GetPosition(shadeCanvas); + UpdateColorFromPoint(p); + } + } + + /// + /// 根据渐变选择器在渐变画布中的位置改变颜色 + /// + /// 渐变选择器的中心相对于渐变画布的坐标 + protected void UpdateColorFromPoint(Point p) + { + if (p.X < 0) p.X = 0; + if (p.X > shadeCanvas.ActualWidth) p.X = shadeCanvas.ActualWidth; + if (p.Y < 0) p.Y = 0; + if (p.Y > shadeCanvas.ActualHeight) p.Y = shadeCanvas.ActualHeight; + + //计算新的颜色 + HsvColor hsvColor = lastPreciseColor.HasValue ? lastPreciseColor.Value : HsvColor.FromArgb(spectrumSlider.SelectedColor); + if (!lastPreciseColor.HasValue) + { + hsvColor.A = (double)Color.A / 255; + } + hsvColor.S = p.X / shadeCanvas.ActualWidth; + hsvColor.V = 1 - p.Y / shadeCanvas.ActualHeight; + //更新颜色 + UpdateColor(hsvColor.ToArgb(), hsvColor); + } + + /// + /// 更新颜色 + /// + /// 新的颜色 + /// 如果新的颜色是由一个精确的颜色得来的,则应传递精确颜色值,否则传递null + protected void UpdateColor(Color newColor, HsvColor? preciseColor) + { + if (updatingColor) return; + updatingColor = true; + + HsvColor hsvColor = preciseColor.HasValue ? preciseColor.Value : HsvColor.FromArgb(newColor); + lastPreciseColor = preciseColor; + + if (shadeCanvas != null) + { + if (preciseColor == null && hsvColor.S == 0 && hsvColor.V == 0) + { + Canvas.SetLeft(shadeSelector, shadeCanvas.ActualWidth - shadeSelector.ActualWidth / 2); + } + else + { + Canvas.SetLeft(shadeSelector, hsvColor.S * shadeCanvas.ActualWidth - shadeSelector.ActualWidth / 2); + } + Canvas.SetTop(shadeSelector, (1 - hsvColor.V) * shadeCanvas.ActualHeight - shadeSelector.ActualHeight / 2); + if (hsvColor.S > 0) + { + spectrumSlider.Value = hsvColor.H; + } + } + if (Color == newColor) + { + Color = newColor; + ForceUpdateTextBox(); + } + else + { + Color = newColor; + } + + updatingColor = false; + } + + /// + /// 强制更新TextBox中的内容 + /// + public void ForceUpdateTextBox() + { + if (tbA != null) + { + BindingExpression expression = tbA.GetBindingExpression(TextBox.TextProperty); + if (expression != null) + expression.UpdateTarget(); + } + + if (tbR != null) + { + BindingExpression expression = tbR.GetBindingExpression(TextBox.TextProperty); + if (expression != null) + expression.UpdateTarget(); + } + + if (tbG != null) + { + BindingExpression expression = tbG.GetBindingExpression(TextBox.TextProperty); + if (expression != null) + expression.UpdateTarget(); + } + + if (tbB != null) + { + BindingExpression expression = tbB.GetBindingExpression(TextBox.TextProperty); + if (expression != null) + expression.UpdateTarget(); + } + + if (tbHexString != null) + { + BindingExpression expression = tbHexString.GetBindingExpression(TextBox.TextProperty); + if (expression != null) + expression.UpdateTarget(); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/DoubanFM/ColorPicker/ColorSpectrumSlider.cs b/DoubanFM/ColorPicker/ColorSpectrumSlider.cs new file mode 100644 index 0000000..cc115a3 --- /dev/null +++ b/DoubanFM/ColorPicker/ColorSpectrumSlider.cs @@ -0,0 +1,117 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace DoubanFM +{ + /// + /// 颜色频谱选择器 + /// + [TemplatePart(Name="PART_Thumb", Type=typeof(System.Windows.Controls.Primitives.Thumb))] + [TemplatePart(Name="PART_Spectrum", Type=typeof(FrameworkElement))] + public class ColorSpectrumSlider : Slider + { + static ColorSpectrumSlider() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorSpectrumSlider), new FrameworkPropertyMetadata(typeof(ColorSpectrumSlider))); + } + + public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register("SelectedColor", typeof(Color), typeof(ColorSpectrumSlider), new PropertyMetadata(Colors.Red)); + /// + /// 选择的频谱颜色 + /// + public Color SelectedColor + { + get { return (Color)GetValue(SelectedColorProperty); } + set { SetValue(SelectedColorProperty, value); } + } + + /// + /// 用于选择频谱颜色的控件 + /// + System.Windows.Controls.Primitives.Thumb thumb; + /// + /// 用于显示频谱的框架元素 + /// + FrameworkElement spectrum; + + /// + /// 生成 控件的可视化树。 + /// + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + thumb = this.Template.FindName("PART_Thumb", this) as System.Windows.Controls.Primitives.Thumb; + spectrum = this.Template.FindName("PART_Spectrum", this) as FrameworkElement; + } + + /// + /// 按下鼠标左键时触发 + /// + /// 事件数据。 + protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) + { + Point p = e.GetPosition(spectrum); + Value = (p.Y / spectrum.ActualHeight) * (this.Maximum - this.Minimum) + this.Minimum; + this.CaptureMouse(); + this.Focus(); + e.Handled = true; + + base.OnPreviewMouseLeftButtonDown(e); + } + + /// + /// 鼠标移动时触发 + /// + /// 包含事件数据的 。 + protected override void OnMouseMove(MouseEventArgs e) + { + if (this.IsMouseCaptured && e.LeftButton == MouseButtonState.Pressed) + { + Point p = e.GetPosition(spectrum); + Value = (p.Y / spectrum.ActualHeight) * (this.Maximum - this.Minimum) + this.Minimum; + } + base.OnMouseMove(e); + } + + /// + /// 松开鼠标左键时触发 + /// + /// 包含事件数据的 。事件数据将报告已释放了鼠标左键。 + protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) + { + this.ReleaseMouseCapture(); + base.OnMouseLeftButtonUp(e); + } + + /// + /// 颜色更改时触发 + /// + /// 的旧 。 + /// 的新 。 + protected override void OnValueChanged(double oldValue, double newValue) + { + base.OnValueChanged(oldValue, newValue); + + SelectedColor = new HsvColor(1, newValue, 1, 1).ToArgb(); + } + + } +} diff --git a/DoubanFM/ColorPicker/HsvColor.cs b/DoubanFM/ColorPicker/HsvColor.cs new file mode 100644 index 0000000..46086c6 --- /dev/null +++ b/DoubanFM/ColorPicker/HsvColor.cs @@ -0,0 +1,182 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Media; + +namespace DoubanFM +{ + /// + /// 用HSV色彩空间表示的颜色 + /// + public struct HsvColor + { + /// + /// 不透明度 + /// + public double A; + /// + /// 色相 + /// + public double H; + /// + /// 饱和度 + /// + public double S; + /// + /// 亮度 + /// + public double V; + + /// + /// 生成 struct 的新实例。 + /// + /// 不透明度 + /// 色相 + /// 饱和度 + /// 亮度 + public HsvColor(double a, double h, double s, double v) + { + A = a; + H = h; + S = s; + V = v; + } + + /// + /// 从Color类的实例生成的新实例 + /// + /// Color类的实例 + /// + /// 的新实例 + /// + public static HsvColor FromArgb(Color argb) + { + double r = argb.R; + double g = argb.G; + double b = argb.B; + + double delta, min; + double h = 0, s, v; + + min = Math.Min(Math.Min(r, g), b); + v = Math.Max(Math.Max(r, g), b); + delta = v - min; + + if (v == 0.0) + { + s = 0; + } + else + s = delta / v; + + if (s == 0) + h = 0.0; + + else + { + if (r == v) + h = (g - b) / delta; + else if (g == v) + h = 2 + (b - r) / delta; + else if (b == v) + h = 4 + (r - g) / delta; + + h *= 60; + if (h < 0.0) + h = h + 360; + + } + + return new HsvColor { A = (double)argb.A / 255, H = h, S = s, V = v / 255 }; + } + + /// + /// 转换为Color类的新实例 + /// + /// + /// Color类的新实例 + /// + public Color ToArgb() + { + double h = H; + double s = S; + double v = V; + + double r = 0, g = 0, b = 0; + + if (s == 0) + { + r = v; + g = v; + b = v; + } + else + { + int i; + double f, p, q, t; + + if (h == 360) + h = 0; + else + h = h / 60; + + i = (int)Math.Truncate(h); + f = h - i; + + p = v * (1.0 - s); + q = v * (1.0 - (s * f)); + t = v * (1.0 - (s * (1.0 - f))); + + switch (i) + { + case 0: + { + r = v; + g = t; + b = p; + break; + } + case 1: + { + r = q; + g = v; + b = p; + break; + } + case 2: + { + r = p; + g = v; + b = t; + break; + } + case 3: + { + r = p; + g = q; + b = v; + break; + } + case 4: + { + r = t; + g = p; + b = v; + break; + } + default: + { + r = v; + g = p; + b = q; + break; + } + } + + } + + return Color.FromArgb((byte)(A * 255), (byte)(r * 255), (byte)(g * 255), (byte)(b * 255)); + } + } +} diff --git a/DoubanFM/ColorPicker/PopupableColorPicker.xaml b/DoubanFM/ColorPicker/PopupableColorPicker.xaml new file mode 100644 index 0000000..594b13c --- /dev/null +++ b/DoubanFM/ColorPicker/PopupableColorPicker.xaml @@ -0,0 +1,51 @@ + + + + + + + + + + diff --git a/DoubanFM/ColorPicker/PopupableColorPicker.xaml.cs b/DoubanFM/ColorPicker/PopupableColorPicker.xaml.cs new file mode 100644 index 0000000..f8da813 --- /dev/null +++ b/DoubanFM/ColorPicker/PopupableColorPicker.xaml.cs @@ -0,0 +1,70 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace DoubanFM +{ + /// + /// 可弹出的颜色选择器 + /// + public partial class PopupableColorPicker : UserControl + { + public PopupableColorPicker() + { + InitializeComponent(); + } + + #region Color属性 + + /// + /// 选择的颜色 + /// + public Color Color + { + get { return (Color)GetValue(ColorProperty); } + set { SetValue(ColorProperty, value); } + } + + public static readonly DependencyProperty ColorProperty = + DependencyProperty.Register("Color", typeof(Color), typeof(PopupableColorPicker), new FrameworkPropertyMetadata(Colors.White, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); + + #endregion + + #region IsAlphaEnabled属性 + + /// + /// 颜色中是否包含Alpha通道 + /// + public bool IsAlphaEnabled + { + get { return (bool)GetValue(IsAlphaEnabledProperty); } + set { SetValue(IsAlphaEnabledProperty, value); } + } + + public static readonly DependencyProperty IsAlphaEnabledProperty = + DependencyProperty.Register("IsAlphaEnabled", typeof(bool), typeof(PopupableColorPicker), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); + + #endregion + + private void Button_Click(object sender, RoutedEventArgs e) + { + popup.IsOpen = true; + } + } +} diff --git a/DoubanFM/Converters.cs b/DoubanFM/Converters.cs new file mode 100644 index 0000000..cc0ec85 --- /dev/null +++ b/DoubanFM/Converters.cs @@ -0,0 +1,511 @@ +/* + * Author : K.F.Storm + * Email : yk000123 at sina.com + * Website : http://www.kfstorm.com + * */ + +using System.Collections.Generic; +using System.Windows.Data; +using System; +using System.Windows.Media; +using System.Windows; +using System.Windows.Controls; +using DoubanFM.Core; + +namespace DoubanFM +{ + /// + /// 音乐进度条值转换器 + /// + public class SliderThumbWidthConverter : IMultiValueConverter + { + /// + /// 由Slider的Value值确定Slider的Thumb宽度 + /// + public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + double Value = (double)values[0]; + double Minimum = (double)values[1]; + double Maximum = (double)values[2]; + double ret; + if (Math.Abs(Maximum - Minimum) < 1e-5) + ret = 0; + else + ret = (Value - Minimum) / (Maximum - Minimum); + if (ret < 0) + ret = 0; + if (ret > 1) + ret = 1; + return ret; + } + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + } + /// + /// 时间信息值转换器 + /// + public class TimeSpanToStringConverter : IValueConverter + { + private static TimeSpanToStringConverter converter = new TimeSpanToStringConverter(); + /// + /// 由TimeSpan值转换为字符串,用于时间显示 + /// + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + TimeSpan timespan = (TimeSpan)value; + return (timespan.Hours > 0 ? timespan.Hours.ToString() + ":" : "") + (timespan.Minutes < 10 ? "0" : "") + timespan.Minutes + ":" + (timespan.Seconds < 10 ? "0" : "") + timespan.Seconds; + } + /// + /// 由时间字符串转换回TimeSpan值 + /// + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + string value2 = "00:" + (string)value; + return TimeSpan.Parse((string)value2); + } + /// + /// 从时间到字符串的静态转换方法 + /// + /// 时间 + /// 格式化后的字符串 + public static string QuickConvert(TimeSpan value) + { + return (string)converter.Convert(value, typeof(string), null, null); + } + /// + /// 从字符串到时间的静态转换方法 + /// + /// 格式化后的字符串 + /// 时间 + public static TimeSpan QuickConvertBack(string value) + { + return (TimeSpan)converter.ConvertBack(value, typeof(TimeSpan), null, null); + } + } + /// + /// 窗口背景到进度条前景的值转换器 + /// + public class WindowBackgroundToSliderForegroundConverter : IValueConverter + { + /// + /// 由窗口背景转换为进度条前景 + /// + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if (value is SolidColorBrush) + { + SolidColorBrush brush = new SolidColorBrush(ColorFunctions.ReviseBrighter(new HslColor(((SolidColorBrush)value).Color), ColorFunctions.ProgressBarReviseParameter).ToRgb()); + brush.Opacity = ((SolidColorBrush)value).Opacity; + if (brush.CanFreeze) brush.Freeze(); + return brush; + } + return value; + } + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + /// + /// 将Bool值反转的转换器 + /// + public class BoolReverseConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + return !(bool)value; + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + return !(bool)value; + } + } + /// + /// 将Bool值转换为Visibility的转换器 + /// + public class BoolToVisibilityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if (!(bool)value) + { + if (parameter != null) + return parameter; + return Visibility.Hidden; + } + else + { + return Visibility.Visible; + } + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + switch ((Visibility)value) + { + case Visibility.Collapsed: + case Visibility.Hidden: + return false; + case Visibility.Visible: + return true; + default: + return true; + } + } + } + /// + /// 将Bool值反转并转换为Visibility的转换器 + /// + public class BoolReverseToVisibilityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if ((bool)value) + { + if (parameter != null) + return parameter; + return Visibility.Hidden; + } + else + { + return Visibility.Visible; + } + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + switch ((Visibility)value) + { + case Visibility.Collapsed: + case Visibility.Hidden: + return true; + case Visibility.Visible: + return false; + default: + return true; + } + } + } + + /// + /// 窗口背景到桌面歌词前景的值转换器 + /// + public class BackgroundToLyricsForegroundConverter : IValueConverter + { + /// + /// 由窗口背景转换为桌面歌词前景 + /// + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if (value is SolidColorBrush) + { + HslColor color = new HslColor(((SolidColorBrush)value).Color); + color.Alpha = 1.0; + if (color.Lightness < 0.7) color.Lightness = 0.7; + SolidColorBrush brush = new SolidColorBrush(color.ToRgb()); + if (brush.CanFreeze) brush.Freeze(); + return brush; + } + return value; + } + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + /// + /// OpenTypeWeight到FontWeight类型的值转换器 + /// + public class OpenTypeWeightToFontWeightConverter : IValueConverter + { + /// + /// 由OpenTypeWeight转换为FontWeight类型 + /// + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if ((int)value > FontWeights.UltraBold.ToOpenTypeWeight()) + return FontWeights.UltraBold; + if ((int)value < FontWeights.Thin.ToOpenTypeWeight()) + return FontWeights.Thin; + return FontWeight.FromOpenTypeWeight((int)value); + } + /// + /// 由FontWeight类型转换为OpenTypeWeight + /// + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + return ((FontWeight)value).ToOpenTypeWeight(); + } + } + + /// + /// 将比例转换为值的转换器 + /// + public class RatioToValueConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + try + { + double ratio = (double)values[0]; + double total = (double)values[1]; + return (double)total * (double)ratio; + } + catch + { + return 0; + } + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + /// + /// 将不透明度转换为透明度的转换器 + /// + public class OpacityToTransparencyConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + return 1.0 - (double)value; + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + return 1.0 - (double)value; + } + } + /// + /// 将透明度转换为不透明度的转换器,避免完全透明 + /// + public class TransparencyToOpacityAndPreventFullTransparentConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if ((double)value == 1) + return 0.01; + return 1.0 - (double)value; + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if ((double)value == 0) + return 0.99; + return 1.0 - (double)value; + } + } + /// + /// 将任意颜色转换为RGB值相同的透明色 + /// + public class ToTransparentColorConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + return Color.FromArgb(0, ((Color)value).R, ((Color)value).G, ((Color)value).B); + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + /// + /// 将HorizontalAlignment转换为RenderTransformOrigin + /// + public class HorizontalAlignmentToRenderTransformOriginConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + switch ((HorizontalAlignment)value) + { + case HorizontalAlignment.Center: + case HorizontalAlignment.Stretch: + return new Point(0.5, 0.5); + case HorizontalAlignment.Left: + return new Point(0, 0.5); + case HorizontalAlignment.Right: + return new Point(1, 0.5); + default: + return new Point(0.5, 0.5); + } + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + /// + /// 将HorizontalAlignment转换为字符串 + /// + public class HorizontalAlignmentToStringConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + switch ((HorizontalAlignment)value) + { + case HorizontalAlignment.Center: + return DoubanFM.Resources.Resources.CenterAlignment; + case HorizontalAlignment.Left: + return DoubanFM.Resources.Resources.LeftAlignment; + case HorizontalAlignment.Right: + return DoubanFM.Resources.Resources.RightAlignment; + case HorizontalAlignment.Stretch: + return DoubanFM.Resources.Resources.StretchAlignment; + default: + return string.Empty; + } + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + /// + /// 将VerticalAlignment转换为字符串 + /// + public class VerticalAlignmentToStringConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + switch ((VerticalAlignment)value) + { + case VerticalAlignment.Center: + return DoubanFM.Resources.Resources.CenterAlignment; + case VerticalAlignment.Top: + return DoubanFM.Resources.Resources.TopAlignment; + case VerticalAlignment.Bottom: + return DoubanFM.Resources.Resources.BottomAlignment; + case VerticalAlignment.Stretch: + return DoubanFM.Resources.Resources.StretchAlignment; + default: + return string.Empty; + } + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + /// + /// 将Share.Sites转换为字符串 + /// + public class ShareSitesToStringConverter : IValueConverter + { + public static Dictionary SiteName; + + static ShareSitesToStringConverter() + { + SiteName = new Dictionary + { + { Core.Share.Sites.Douban, Resources.Resources.ShareSiteDouban }, + { Core.Share.Sites.Facebook, Resources.Resources.ShareSiteFacebook }, + { Core.Share.Sites.Fanfou, Resources.Resources.ShareSiteFanfou }, + { Core.Share.Sites.Kaixin, Resources.Resources.ShareSiteKaixin }, + { Core.Share.Sites.Msn, Resources.Resources.ShareSiteMsn }, + { Core.Share.Sites.Renren, Resources.Resources.ShareSiteRenren }, + { Core.Share.Sites.TencentWeibo, Resources.Resources.ShareSiteTencentWeibo }, + { Core.Share.Sites.Twitter, Resources.Resources.ShareSiteTwitter }, + { Core.Share.Sites.Weibo, Resources.Resources.ShareSiteWeibo }, + { Core.Share.Sites.Qzone, Resources.Resources.ShareSiteQzone }, + { Core.Share.Sites.None, Resources.Resources.ShareSiteNone } + }; + } + + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if (Enum.IsDefined(typeof(Core.Share.Sites), value)) + { + return SiteName[(Core.Share.Sites)value]; + } + else + { + return null; + } + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + /// + /// 根据频道确定能否使用收藏功能 + /// + public class ChannelToCanFavoriteVisibilityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + Core.Channel channel = value as Core.Channel; + if (channel == null) + { + channel = (value as Core.ChannelSearchItem).GetChannel(); + } + if (channel == null) + { + return Visibility.Collapsed; + } + bool canFavorite = canFavorite = !channel.IsPersonal || channel.IsSpecial; + return canFavorite ? Visibility.Visible : Visibility.Collapsed; + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + public class TextBoxHintConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + bool isFocused = (bool)values[0]; + string text = (string)values[1]; + bool canShow = !isFocused && string.IsNullOrEmpty(text); + return canShow ? Visibility.Visible : Visibility.Collapsed; + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + /// + /// 根据一个Boolean值的真假选择两个值中的一个 + /// + public class BooleanChooserConverter : IMultiValueConverter + { + public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if ((bool)values[0]) + { + return values[1]; + } + else + { + return values[2]; + } + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/DoubanFM/DoubanFM.csproj b/DoubanFM/DoubanFM.csproj new file mode 100644 index 0000000..3428aa9 --- /dev/null +++ b/DoubanFM/DoubanFM.csproj @@ -0,0 +1,398 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {DDDAF282-C866-4036-AAF0-146D6D74080B} + WinExe + Properties + DoubanFM + DoubanFM + v4.0 + Client + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + 4.0.30816.0 + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + true + bin\Debug\ + TRACE;DEBUG + bin\Debug\DoubanFM.XML + full + AnyCPU + bin\Debug\DoubanFM.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + true + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + true + + + bin\Release\ + TRACE + true + pdbonly + AnyCPU + bin\Release\DoubanFM.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + true + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + true + + + icon.ico + + + false + + + + LocalIntranet + + + true + + + Properties\app.manifest + + + + + + + + + + + + + + + + ..\WPFSoundVisualizationLib.dll + + + + + MSBuild:Compile + Designer + + + + + + + + PopupableColorPicker.xaml + + + + + + + + + + + + + + + Resources.zh-CN.resx + True + True + + + Resources.resx + True + True + + + ShadowWindow.xaml + + + + ExceptionWindow.xaml + + + + HelpWindow.xaml + + + + PopupControlPanel.xaml + + + BalloonSongInfo.xaml + + + PopupLiked.xaml + + + UISettingWindow.xaml + + + GeneralSettingWindow.xaml + + + + + HotKeySettingWindow.xaml + + + + LyricsSettingWindow.xaml + + + LyricsWindow.xaml + + + + ShareSettingWindow.xaml + + + Style.xaml + + + VolumeControl.xaml + + + + + + + + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + + + DoubanFMWindow.xaml + Code + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + + + Code + + + Designer + PublicResXFileCodeGenerator + Resources.Designer.cs + + + Designer + PublicResXFileCodeGenerator + Resources.zh-CN.Designer.cs + + + Designer + + + + + + + {62324CFD-03FF-44B4-9204-66BAE86972B6} + DoubanFM.Bass + + + {AA75B5E6-F373-49D7-B2E0-16C3E57321F7} + DoubanFM.Core + + + {368cdbe6-0ba2-4dad-aceb-fbb8eedb1bd7} + DwmHelper + + + {7AC63864-7638-41C4-969C-D3197EF2BED9} + NotifyIconWpf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + Microsoft .NET Framework 4 Client Profile %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + xcopy /y "$(SolutionDir)version.dat" "$(TargetDir)" + + + \ No newline at end of file diff --git a/DoubanFM/DoubanFMWindow.xaml b/DoubanFM/DoubanFMWindow.xaml new file mode 100644 index 0000000..9e18f85 --- /dev/null +++ b/DoubanFM/DoubanFMWindow.xaml @@ -0,0 +1,741 @@ + + + + + + + + + + + + + + + + + + + + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Images/DoubanFM_Pause.png + Images/DoubanFM_Play.png + Images/DoubanFM_Next.png + Images/DoubanFM_Like_Like.png + Images/DoubanFM_Like_Disabled.png + Images/DoubanFM_Like_Unlike.png + Images/DoubanFM_Never.png + Images/DoubanFM_Never_Disabled.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +