Есть отличная библиотека bass.NET которая может проигрывать любые аудио файлы, она почти бесплатна
Для начало определим что будет в приложении. 1 - кнопка проигрывания, 2 - визуальный эффект, ну как в Windows Media Player, 3 - кнопка смены качества. Ну и на последок сделаем его красивым, добавив MetroUI,
Шаг 1. Добавим нужные библиотеки
Из bass.NET нужно только 2 файла - bass.dll, и bass.Net.dll
из MetroUI нужен Metroframework.dll
Шаг 2. Я не буду описывать работать с MetroUI, но скажу только что достаточно его подключить через References из студии, и в главной форме Form1 написать
Шаг 4. Метод Play() принимает несколько важных аргументов, точнее всего 1, но оочень важный, угадаете** ? - это ссылка на файл.
Шаг 5. Спектрум
Тут выбор очень хороший, будем использовать всё что есть
Шаг .. какойта там
Обернем весь код, что бы было проще обращаться, и в отдельную библиотеку
Настало время использовать все это добро
Для начало определим что будет в приложении. 1 - кнопка проигрывания, 2 - визуальный эффект, ну как в Windows Media Player, 3 - кнопка смены качества. Ну и на последок сделаем его красивым, добавив MetroUI,
Шаг 1. Добавим нужные библиотеки
Из bass.NET нужно только 2 файла - bass.dll, и bass.Net.dll
из MetroUI нужен Metroframework.dll
Шаг 2. Я не буду описывать работать с MetroUI, но скажу только что достаточно его подключить через References из студии, и в главной форме Form1 написать
public partial class Form1 : MetroFramework.Forms.MetroFormШаг 3. Маленька обертка для упрощения обращения с Bass.NET, в основном нам понадобятся методы Play() ну и так понятно что для плейнга сонга, GetSpectrum() для получения изображении спектра. Звучит заманчиво? Басс нет предоставляет куча-вар-иантов спектрума, воспользуемся всеми. + еще одни хандлер для перебора спектрумов (пусть это будет PictureBox Click event handler)
Шаг 4. Метод Play() принимает несколько важных аргументов, точнее всего 1, но оочень важный, угадаете** ? - это ссылка на файл.
public void Play() { if (Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero)) { //stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_DEFAULT); stream = Bass.BASS_StreamCreateURL(_url, 0, BASSFlag.BASS_DEFAULT, null, IntPtr.Zero); if (stream != 0) { Bass.BASS_ChannelPlay(stream, false); vs = new Visuals(); } else { throw new Exception(string.Format("Stream error: {0}", Bass.BASS_ErrorGetCode())); } } }Здесь как видно, Bass имеет два метода, из файла, или из ссылки, остальные аргумены трогать не стоит, аргумент _url определен как строка с адресом на интернет ресурс
Шаг 5. Спектрум
Тут выбор очень хороший, будем использовать всё что есть
public enum Waves { Line = 0, Bean = 1, Dot = 2, //Elipse = 3, LinePeak = 4, Wave = 5 }Теперь метод для получения того самого спектрума ** странное слово
public Image GetSpectrum(Waves waveType) { if (stream != 0) { if (vs != null) { switch (waveType) { case Waves.Line: return (Image)vs.CreateSpectrumLine(stream, _width, _height, _colorBase, _colorPeak, _colorBackground, _thickness, _distance, false, true, true); case Waves.Bean: return (Image)vs.CreateSpectrumBean(stream, _width, _height, _colorBase, _colorPeak, _colorBackground, _thickness, false, true, true); case Waves.Dot: return (Image)vs.CreateSpectrumDot(stream, _width, _height, _colorBase, _colorPeak, _colorBackground, _thickness, _distance, false, true, true); //case Waves.Elipse: // return (Image)vs.CreateSpectrumEllipse(stream, _width, _height, _colorBase, _colorPeak, _colorBackground, _thickness, _distance, false, true, true); case Waves.LinePeak: return (Image)vs.CreateSpectrumLinePeak(stream, _width, _height, _colorBase, Color.White, _colorBase, _colorBackground, _thickness, _thickness, _distance, 5, false, true, true); case Waves.Wave: return (Image)vs.CreateSpectrumWave(stream, _width, _height, _colorBase, _colorPeak, _colorBackground, _thickness, false, true, true); default: return (Image)vs.CreateSpectrumLine(stream, _width, _height, _colorBase, _colorPeak, _colorBackground, _thickness, _distance, false, true, true); } } } return null; }Откуда все эти vs? _widht? _colorBase? это просто поля которые мы настраиваем под наше приложение, width height означают высоту ширину картинки, дада, метод возвращает картинку, которые мы будем ежесекундно перезавать в наш picturebox, и понадобится таймер, ну и что бы приложение было красивым я использовал metroui в синем-белов цвете, и что бы спектрум соответсвтовал цветовой гамме, мы и передаем _colorBase и прочее, ниже полный список
private Un4seen.Bass.Misc.Visuals vs; private int stream; private string _url; public string URL { get { return _url; } set { _url = value; } } private Timer timer1; private Color _colorBase = Color.Black; public Color ColorBase { get { return _colorBase; } set { _colorBase = value; } } private Color _colorPeak = Color.Gray; public Color ColorPeak { get { return _colorPeak; } set { _colorPeak = value; } } private Color _colorBackground = Color.White; public Color ColorBackground { get { return _colorBackground; } set { _colorBackground = value; } } private int _width = 200; public int Width { get { return _width; } set { _width = value; } } private int _height = 50; public int Height { get { return _height; } set { _height = value; } } private int _thickness = 1; public int Thickness { get { return _thickness; } set { _thickness = value; } } private int _distance = 3; public int Distance { get { return _distance; } set { _distance = value; } }vs - объект передающий спектрумы, ColorBase - основной цвет ColorPeak - цвет при пике этой пригающей полоски ColorBackground - тут все понятно timer1 - получаем картинки height, width - размеры спектрума thickness размер полоски спектрума distance - дистанция между полосками спектрума Как видите настрайвать тут много чего можно, ну можно и дефолтные использовать
Шаг .. какойта там
Обернем весь код, что бы было проще обращаться, и в отдельную библиотеку
using Un4seen.Bass; using Un4seen.Bass.Misc; namespace EuropaPlus { public enum Waves { Line = 0, Bean = 1, Dot = 2, //Elipse = 3, LinePeak = 4, Wave = 5 } public class Engine : IDisposable { private Un4seen.Bass.Misc.Visuals vs; private int stream; private string _url; public string URL { get { return _url; } set { _url = value; } } private Timer timer1; private Color _colorBase = Color.Black; public Color ColorBase { get { return _colorBase; } set { _colorBase = value; } } private Color _colorPeak = Color.Gray; public Color ColorPeak { get { return _colorPeak; } set { _colorPeak = value; } } private Color _colorBackground = Color.White; public Color ColorBackground { get { return _colorBackground; } set { _colorBackground = value; } } private int _width = 200; public int Width { get { return _width; } set { _width = value; } } private int _height = 50; public int Height { get { return _height; } set { _height = value; } } private int _thickness = 1; public int Thickness { get { return _thickness; } set { _thickness = value; } } private int _distance = 3; public int Distance { get { return _distance; } set { _distance = value; } } public Engine(string Url, Color Base, Color Peak, Color Background, int width, int height, int thickness, int distance) { this._url = Url; this._colorBase = Base; this._colorPeak = Peak; this._colorBackground = Background; this._width = width; this._height = height; this._thickness = thickness; this._distance = distance; } public Engine(string Url, Color Base, Color Peak, Color Background, int width, int height) { this._url = Url; this._colorBase = Base; this._colorPeak = Peak; this._colorBackground = Background; this._width = width; this._height = height; } public Engine(string Url, int width, int height) { this._url = Url; this._width = width; this._height = height; } public Engine(string Url) { this._url = Url; } ////// Custom spectrum wave from 'url' /// ///Image public void Play() { if (Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero)) { //stream = Bass.BASS_StreamCreateFile("test.mp3", 0, 0, BASSFlag.BASS_DEFAULT); stream = Bass.BASS_StreamCreateURL(_url, 0, BASSFlag.BASS_DEFAULT, null, IntPtr.Zero); if (stream != 0) { Bass.BASS_ChannelPlay(stream, false); vs = new Visuals(); } else { throw new Exception(string.Format("Stream error: {0}", Bass.BASS_ErrorGetCode())); } } } public void FlushSpectrum() { vs = new Visuals(); } public Image GetSpectrum(Waves waveType) { if (stream != 0) { if (vs != null) { switch (waveType) { case Waves.Line: return (Image)vs.CreateSpectrumLine(stream, _width, _height, _colorBase, _colorPeak, _colorBackground, _thickness, _distance, false, true, true); case Waves.Bean: return (Image)vs.CreateSpectrumBean(stream, _width, _height, _colorBase, _colorPeak, _colorBackground, _thickness, false, true, true); case Waves.Dot: return (Image)vs.CreateSpectrumDot(stream, _width, _height, _colorBase, _colorPeak, _colorBackground, _thickness, _distance, false, true, true); //case Waves.Elipse: // return (Image)vs.CreateSpectrumEllipse(stream, _width, _height, _colorBase, _colorPeak, _colorBackground, _thickness, _distance, false, true, true); case Waves.LinePeak: return (Image)vs.CreateSpectrumLinePeak(stream, _width, _height, _colorBase, Color.White, _colorBase, _colorBackground, _thickness, _thickness, _distance, 5, false, true, true); case Waves.Wave: return (Image)vs.CreateSpectrumWave(stream, _width, _height, _colorBase, _colorPeak, _colorBackground, _thickness, false, true, true); default: return (Image)vs.CreateSpectrumLine(stream, _width, _height, _colorBase, _colorPeak, _colorBackground, _thickness, _distance, false, true, true); } } } return null; } public void Dispose() { Bass.BASS_Free(); this._url = null; this.stream = 0; vs = null; } } }
Настало время использовать все это добро
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows.Forms; using Un4seen.Bass; using Un4seen.Bass.Misc; using MetroFramework; namespace EuropaPlus { public partial class Form1 : MetroFramework.Forms.MetroForm { public Form1() { InitializeComponent(); //this.Size = new Size(190, 173); this.metroButton1.Size = new Size(150, 80); this.metroButton1.Location = new Point(20, 60); //this.pictureBox1.Size = new Size(150, 80); //this.pictureBox1.Location = new Point(20, 60); this.metroButton1.Text = "Play"; this.metroToggle1.Visible = false; this.metroToggle2.Visible = false; wvv = Waves.Line; rnd = new Random(); } private bool animDone = false; private bool animDone2 = false; private Random rnd; private Waves wvv; private Engine eng; private const string music = "http://ep256.streamr.ru"; private const string music2 = "http://ep128.streamr.ru"; private MetroFramework.Animation.MoveAnimation mvAnimBut; //private MetroFramework.Animation.ExpandAnimation exAnimForm; private MetroFramework.Animation.ExpandAnimation exAnimBut; private void StartGrabbing() { eng.FlushSpectrum(); timer1.Stop(); timer1.Interval = 100; timer1.Start(); } private void timer1_Tick(object sender, EventArgs e) { GetImages(); } private void GetImages() { this.pictureBox1.Image = eng.GetSpectrum(wvv); } private void metroButton1_Click(object sender, EventArgs e) { if (animDone2 == true) { eng.Dispose(); if (metroToggle2.CheckState == CheckState.Checked) eng = new Engine(music, this.pictureBox1.Width, this.pictureBox1.Height); else eng = new Engine(music2, this.pictureBox1.Width, this.pictureBox1.Height); eng.Thickness = 1; eng.Distance = 0; eng.ColorBase = Color.DeepSkyBlue; if (metroStyleManager1.Theme == MetroThemeStyle.Light) eng.ColorBackground = Color.White; else eng.ColorBackground = Color.FromArgb(19, 19, 19); eng.ColorPeak = Color.DeepSkyBlue; eng.Play(); StartGrabbing(); } else { try { if (metroToggle2.CheckState == CheckState.Checked) eng = new Engine(music, this.pictureBox1.Width, this.pictureBox1.Height); else eng = new Engine(music2, this.pictureBox1.Width, this.pictureBox1.Height); eng.Thickness = 1; eng.Distance = 0; eng.ColorBase = Color.DeepSkyBlue; if (metroStyleManager1.Theme == MetroThemeStyle.Light) eng.ColorBackground = Color.White; else eng.ColorBackground = Color.FromArgb(19, 19, 19); eng.ColorPeak = Color.DeepSkyBlue; eng.Play(); StartGrabbing(); DoAnim(); animDone2 = true; } catch (Exception ee) { MessageBox.Show(ee.Message); return; } } } private void DoAnim() { if (animDone == false) { mvAnimBut = new MetroFramework.Animation.MoveAnimation(); exAnimBut = new MetroFramework.Animation.ExpandAnimation(); //exAnimForm = new MetroFramework.Animation.ExpandAnimation(); exAnimBut.Start(metroButton1, new Size(48, 17), MetroFramework.Animation.TransitionType.EaseOutExpo, 50); //exAnimForm.Start(this, new Size(600, 200), MetroFramework.Animation.TransitionType.EaseOutExpo, 50); mvAnimBut.Start(this.metroButton1, new Point(74, 128), MetroFramework.Animation.TransitionType.EaseOutCubic, 50); this.metroToggle1.Visible = true; this.metroToggle2.Visible = true; animDone = true; this.metroButton1.Text = "Playing"; } } private void Form1_Load(object sender, EventArgs e) { } private void metroToggle1_CheckedChanged(object sender, EventArgs e) { if (this.metroStyleManager1.Theme == MetroThemeStyle.Light) { this.metroStyleManager1.Theme = MetroThemeStyle.Dark; eng.ColorBackground = Color.FromArgb(19,19,19); } else { this.metroStyleManager1.Theme = MetroThemeStyle.Light; eng.ColorBackground = Color.White; } } private void metroToggle2_CheckedChanged(object sender, EventArgs e) { if (metroToggle2.CheckState == CheckState.Checked) { eng.Dispose(); eng = new Engine(music, this.pictureBox1.Width, this.pictureBox1.Height); eng.Thickness = 1; eng.Distance = 0; eng.ColorBase = Color.DeepSkyBlue; if (metroStyleManager1.Theme == MetroThemeStyle.Light) eng.ColorBackground = Color.White; else eng.ColorBackground = Color.FromArgb(19, 19, 19); eng.ColorPeak = Color.DeepSkyBlue; eng.Play(); StartGrabbing(); } else { eng.Dispose(); eng = new Engine(music2, this.pictureBox1.Width, this.pictureBox1.Height); eng.Thickness = 1; eng.Distance = 0; eng.ColorBase = Color.DeepSkyBlue; if (metroStyleManager1.Theme == MetroThemeStyle.Light) eng.ColorBackground = Color.White; else eng.ColorBackground = Color.FromArgb(19, 19, 19); eng.ColorPeak = Color.DeepSkyBlue; eng.Play(); StartGrabbing(); } } //http://ep128.streamr.ru private void pictureBox1_Click(object sender, EventArgs e) { wvv = (Waves)rnd.Next(5); StartGrabbing(); } } }Теперь по порядку, приложение запускается, появляется милинькое окошко
при нажатии Play приложение вызывает
private void metroButton1_Click(object sender, EventArgs e) { if (animDone2 == true) { eng.Dispose(); if (metroToggle2.CheckState == CheckState.Checked) eng = new Engine(music, this.pictureBox1.Width, this.pictureBox1.Height); else eng = new Engine(music2, this.pictureBox1.Width, this.pictureBox1.Height); eng.Thickness = 1; eng.Distance = 0; eng.ColorBase = Color.DeepSkyBlue; if (metroStyleManager1.Theme == MetroThemeStyle.Light) eng.ColorBackground = Color.White; else eng.ColorBackground = Color.FromArgb(19, 19, 19); eng.ColorPeak = Color.DeepSkyBlue; eng.Play(); StartGrabbing(); } else { try { if (metroToggle2.CheckState == CheckState.Checked) eng = new Engine(music, this.pictureBox1.Width, this.pictureBox1.Height); else eng = new Engine(music2, this.pictureBox1.Width, this.pictureBox1.Height); eng.Thickness = 1; eng.Distance = 0; eng.ColorBase = Color.DeepSkyBlue; if (metroStyleManager1.Theme == MetroThemeStyle.Light) eng.ColorBackground = Color.White; else eng.ColorBackground = Color.FromArgb(19, 19, 19); eng.ColorPeak = Color.DeepSkyBlue; eng.Play(); StartGrabbing(); DoAnim(); animDone2 = true; } catch (Exception ee) { MessageBox.Show(ee.Message); return; } } }в котором описано поведение, то есть кнопка уменьшается, движется в середину, и изменяется текст, и в соответсви с выбранной темой, все преобразуется в некую гамму, ну чесно говоря в коде все итак понятно, думаю никчему больше слов, )) Исходник на Github