C ා simply use the Bass.Net audio decoder

There are many audio playing schemes in C, for example, WinForm calls the COM component of MediaPlayer and the MediaPlayer of WPF

And a bunch of API playback and DirectX

So I found Bass (the main program is based on C++ C ා and can be called through the official library Bass.Net), which is an efficient and compact audio decoder for the whole platform

I. start

First, you need to download the bass.dll main program file (about 257kb) on the official website: http://www.un4seen.com/

And class library (. Net platform call): you can http://www.bass.radio42.com/bass_register.html Use your email to register to a key and download bass. Net. DLL (about 520kb)

Official documents: http://www.bass.radio42.com/help/

P.S:bass.dll should be placed in the main directory of the program at will (added to the assembly reference)

 

Two, encoding

Before you start, you need to register the program and initialize the Bass decoder:

using Un4seen.Bass;//Add reference
...
BassNet.Registration("Your mailbox", "You registered to Key");
Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_CPSPEAKERS, If there is no window handle, it will IntPtr.Zero);

1. Realize simple mp3 playback

There are two ways to play mp3: load from file, load from URL

Example 1: load from file:

//---------Method called to------------
public static int BASS_StreamCreateFile(
    string file,//File path
    long offset,//Offset, generally not used
    long length,//If you use an offset, define the read length after an offset
    BASSFlag flags//How to create a flow
)
//Help links and other information:http://www.bass.radio42.com/help/html/e49e005c-52c0-fc33-e5f9-f27f2e0b1c1f.htm
//----------------------------------

//Creating streams id,Recommended as a global variable(If it's a playlist file)
private int stream =  -1024;//You can define an initial value yourself
...
//Create a simple FLOAT Audio stream,Return stream id Easy to control and query
stream = Bass.BASS_StreamCreateFile(Your file full path, 0L, 0L, BASSFlag.BASS_SAMPLE_FLOAT);
... Start playing
//parameter:int Of the stream to play id,bool Do you want to play again after playing
Bass.BASS_ChannelPlay(stream, false);
... Pause playback
Bass.BASS_ChannelPause(stream);

 

Example 2: load from URL:

stream = Bass.BASS_StreamCreateURL(url, 0, BASSFlag.BASS_SAMPLE_FLOAT, null, IntPrt.Zero);

It's just that the way the audio stream is loaded has changed, and the rest is consistent

If you need some other features (headers and download callbacks when requesting a Url), see the following:

1. Add URL request header:

Very simple: just add in the url parameter, and use "\ r\n" to wrap between the url and each header, for example:

stream = Bass.BASS_StreamCreateURL(url+"\r\n"+"A header, Header:Content"+"\r\n"+"Another header",...);

2. Download callback: mostly used for caching

//Must be a global variable, otherwise it will be GC Recycle!
private DOWNLOADPROC _myDownloadProc;
private FileStream _fs = null;//Stream written to file
private byte[] _data; // Local cache

...
//Add invocation
 _myDownloadProc = new DOWNLOADPROC(DownloadCallBack);
...

//Download callback, by Bass call
private void DownloadCallBack(IntPtr buffer, int length, IntPtr user)
        {
            // file length
            long len = Bass.BASS_StreamGetFilePosition(stream, BASSStreamFilePosition.BASS_FILEPOS_END);
            // download progress
            long down = Bass.BASS_StreamGetFilePosition(stream, BASSStreamFilePosition.BASS_FILEPOS_DOWNLOAD);
            //Download progress can be added here Callback

            if (_fs == null)
            {
                // Start downloading, open file stream
               //pit:When you cut the song, Bass It will not continue to download and will send you the downloaded logo. At this time, the file you get is incomplete!So this is the first step.cache download
                _fs = File.OpenWrite(Saved path + ".cache");
            }
            if (buffer == IntPtr.Zero)
            {
                // Download complete
                _fs.Flush();
                _fs.Close();
                _fs = null;
                FileInfo fi = new FileInfo(DLPath + ".cache");
               //Delete if the download is incomplete.cache
                if (fi.Length != len)
                {
                    fi.Delete();
                }
                else
                {
                    //Move to cache if download is complete(download)Catalog
                    fi.MoveTo(Your path, true);
                    //Here you can do the callback after downloading
                }
            }
            else
            {
                //Accept the download data, essentially Bass Pointer to the data, C#Copy data from memory by pointer
                // 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);
            }
        }

 

2. Get and set some general data (play progress, sound):

1. Set and get volume:

//Set the volume value to 0~1 The default value between is 1
Bass.BASS_ChannelSetAttribute(stream, BASSAttribute.BASS_ATTRIB_VOL, value);

...

//Get current volume ref value
float value=0;
Bass.BASS_ChannelGetAttribute(stream, BASSAttribute.BASS_ATTRIB_VOL,ref value);

2. Playback progress and total length (time):

 //length
public TimeSpan GetLength
        {
            get
            {
                double seconds = Bass.BASS_ChannelBytes2Seconds(stream, Bass.BASS_ChannelGetLength(stream));
                return TimeSpan.FromSeconds(seconds);
            }
        }
//Current playing position
public TimeSpan Position
        {
            get
            {
                double seconds = Bass.BASS_ChannelBytes2Seconds(stream, Bass.BASS_ChannelGetPosition(stream));
                return TimeSpan.FromSeconds(seconds);
            }
            set => Bass.BASS_ChannelSetPosition(stream, value.TotalSeconds);
        }

To obtain FFT data, you can use this data to do the spectrum:

//Get 256 bit FFT Data, of course, you can choose a bigger one, but it's enough
//pit:Obtained when the playback is paused FFT Data is still not suspended before the data(Stay in this position FFT)If you need to do spectrum mapping, you should manually set it to 0 when pausing because Bass Does not return 0 on pause
float[] fft = new float[256];
Bass.BASS_ChannelGetData(stream, fft, (int)BASSData.BASS_DATA_FFT256);

Unfortunately, Bass doesn't provide a callback for playback completion. You need to set a Timer to determine whether the playback is completed. In theory, when the current position = the total length of playback, the playback is completed

 

3. Update equipment and end

1. The system will place the current default device in the [0] bit of the collection, but Bass will not automatically update the device or update the event callback of the device (or I did not find?), so you need to check whether there is a new device inserted by yourself, and you need to manually update the device (if necessary)

public void UpdataDevice()
        {
            var data = Bass.BASS_GetDeviceInfos();
            int index = -1;
            for (int i = 0; i < data.Length; i++)
                if (data[i].IsDefault)
                {
                    index = i;
                    break;
                }
            if (!data[index].IsInitialized)
                Bass.BASS_Init(index, 44100, BASSInit.BASS_DEVICE_CPSPEAKERS, wind);
            var a = Bass.BASS_ChannelGetDevice(stream);
            if (a != index)
            {
                Bass.BASS_ChannelSetDevice(stream, index);
                Bass.BASS_SetDevice(index);
            }
        }

 

2. At the end, the stream and Bass decoder need to be released:

Bass.BASS_ChannelStop(stream);
Bass.BASS_StreamFree(stream);
Bass.BASS_Stop();
Bass.BASS_Free();

 

4. Double speed playback and other FX Effects

Why do we need to restart the title here?

This method overturns the stream creation form previously used, but the methods such as controlling playback pause remain unchanged.

First, you need to introduce several Bass concepts:

Audio stream: stream, used for playing audio, that is, the stream you control when playing pause

Decode stream decode, used to decode audio, and then pass it to Fx effector, Fx effector will return an audio stream to you

 

To implement this method, you need to download the FX extension (just choose add-on in bass.dll), about 85kb

Add using reference:

using Un4seen.Bass.AddOn.Fx;

Create stream:

//Global variables, decoding streams
private int decode;

decode = Bass.BASS_StreamCreateFile(Your document, 0L, 0L, BASSFlag.BASS_STREAM_DECODE);
//You only need to change the label to BASS_STREAM_DECODE Yes, CreateURL The same is true.

//Pass the decode stream in Fx In the effector, you will get an audio stream
stream = BassFx.BASS_FX_TempoCreate(decode, BASSFlag.BASS_FX_FREESOURCE );

Set Fx effect:

Value value is between - 90 ~ 0 ~ 5000, calculated in percentage system. For example, if acceleration / deceleration play is 10%, then value=10, no need to play multiple speed play value=0, deceleration value=-10

Bass.BASS_ChannelSetAttribute(stream, BASSAttribute.BASS_ATTRIB_TEMPO, value);

The method of obtaining Fx effect is the same as the volume. Just change the label bassattribute.bass? Attrib? Tempo

For more FX effects, please refer to: http://www.bass.radio42.com/help/html/90d034c4-b426-7f7c-4f32-28210a5e6bfb.htm ljust modify the label and value values as you would

 

 

 

End... Thanks!

What's the problem

QQ:2728578956 (Twilight./Lemon)

Tags: C# MediaPlayer encoding REST

Posted on Wed, 11 Mar 2020 05:02:28 -0700 by themaxx113