一个游戏对象只能使用一个unity3d audio sourcesource么

Unity3D 游戏引擎之详解游戏开发音频的播放(十五)
我的图书馆
Unity3D 游戏引擎之详解游戏开发音频的播放(十五)
&Unity3D 游戏引擎之详解游戏开发音频的播放&& & & &游戏音频的播放在任何游戏中都占据非常重要的地位,音频的播放还可以分为两种,一种为游戏音乐,另一种为游戏音效。前者适用于较长的音乐,如游戏背景音乐。第二种试用与比较短的游戏音乐,如开枪,打怪 时“砰砰”一瞬间播放的游戏音效。今天MOMO将用下面的例子带盆友们去剖析Unity3D游戏音乐与音效的播放。&Unity3D游戏引擎一共支持4个音乐格式的文件.AIFF& 适用于较短的音乐文件可用作游戏打斗音效.WAV& 适用于较短的音乐文件可用作游戏打斗音效.MP3& 适用于较长的音乐文件可用作游戏背景音乐.OGG& 适用于较长的音乐文件可用作游戏背景音乐&& & &在场景中创建一个空的游戏对象。GameObject -& CreateEmpty& 创建成功后我命名为audio。给audio添加一个AudioSource属性,这个属性非常的重要,Unity播放音乐主要就是要靠这个东西。Component -& Audio - & Audio Source。找一个音乐文件,我这里使用了一个.mp3音乐文件,我命名为0.mp3 如下图所示将它拖动到右侧Audio Clip处。&我们发现 Audio Source 有很多设置的属性,那么MOMO将一些比较重要的属性诺列出来。AudioClip :声音片段,还可以在代码中去动态的截取音乐文件。Mute : 是否静音Bypass Effects: 是否打开音频特效Play On Awake: 开机自动播放Loop:循环播放Volume: 声音大小,取值范围0.0 到 1.0Pitch:播放速度,取值范围在 -3 到 3 之间 设置1 为正常播放,小于1 为减慢播放 大于1为加速播放。创建一个脚本我命名为audio.cs 用来音乐的播放。本章将实现3个按钮 点击实现 播放音乐、 停止音乐、 暂停音乐 ,与一个横向拖动条通过手指的拖动实现动态修改音乐声音。audio.cs&&using&UnityE&&&using&System.C&&&&&&public&class&audio&:&MonoBehaviour&{&&&&&&&&&&//音乐文件&&&&&&&public&AudioSource&&&&&&&&&&&//音量&&&&&&&public&float&musicV&&&&&&&&&&&&&&&&&void&Start()&{&&&&&&&&&&&&//设置默认音量&&&&&&&&&&&&musicVolume&=&0.5F;&&&&&&&&&&&}&&&&&&&void&OnGUI()&{&&&&&&&&&&&&&&&&&&&&&&//播放音乐按钮&&&&&&&&&&&if&(GUI.Button(new&Rect(10,&10,&100,&50),&"Play&music"))&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//没有播放中&&&&&&&&&&&&&&&if&(!music.isPlaying){&&&&&&&&&&&&&&&&&&&//播放音乐&&&&&&&&&&&&&&&&&&&music.Play();&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&&&//关闭音乐按钮&&&&&&&&&&&if&(GUI.Button(new&Rect(10,&60,&100,&50),&"Stop&music"))&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&if&(music.isPlaying){&&&&&&&&&&&&&&&&&&&//关闭音乐&&&&&&&&&&&&&&&&&&&music.Stop();&&&&&&&&&&&&&&&}&&&&&&&&&&&}&&&&&&&&&&&//暂停音乐&&&&&&&&&&&if&(GUI.Button(new&Rect(10,&110,&100,&50),&"Pause&music"))&&{&&&&&&&&&&&&&&&if&(music.isPlaying){&&&&&&&&&&&&&&&&&&&//暂停音乐&&&&&&&&&&&&&&&&&&&//这里说一下音乐暂停以后&&&&&&&&&&&&&&&&&&&//点击播放音乐为继续播放&&&&&&&&&&&&&&&&&&&//而停止以后在点击播放音乐&&&&&&&&&&&&&&&&&&&//则为从新播放&&&&&&&&&&&&&&&&&&&//这就是暂停与停止的区别&&&&&&&&&&&&&&&&&&&music.Pause();&&&&&&&&&&&&&&&}&&&&&&&&&&&}&&&&&&&&&&&&&&//创建一个横向滑动条用于动态修改音乐音量&&&&&&&&&&&//第一个参数&滑动条范围&&&&&&&&&&&//第二个参数&初始滑块位置&&&&&&&&&&&//第三个参数&起点&&&&&&&&&&&//第四个参数&终点&&&&&&&&&&&musicVolume&=&GUI.HorizontalSlider&(new&Rect(160,&10,&100,&50),&musicVolume,&0.0F,&1.0F);&&&&&&&&&&&&&&&&&&//将音量的百分比打印出来&&&&&&&&&&&GUI.Label(new&Rect(160,&50,&300,&20),&"Music&Volueme&is&"&+&(int)(musicVolume&*&100)&+&"%");&&&&&&&&&&&&&&&&&&&&&&if&(music.isPlaying){&&&&&&&&&&&&&&&//音乐播放中设置音乐音量&取值范围&0.0F到&1.0&&&&&&&&&&&&&&&&music.volume&=&musicV&&&&&&&&&&&}&&&&&&&}&&&}&&&&将audio.cs 绑定在摄像头上,将audio游戏对象拖动赋值给Music 这个AudioSource这个对象。这里强调一下AudioListenr ,它音频监听器,用来监听音乐文件的播放。这是一个重要的属性,一定要勾选,只有勾选后才可以进行音乐的播放。build and run 运行我们这个游戏Demo,一切功能完美实现,哇咔咔~&最后欢迎各位盆友可以和MOMO一起讨论Unity3D游戏开发,大家一起学习一起进步,哇咔咔~~~ 附上Unity3D工程的下载地址,Xcode项目我就不上传了,须要的自己导出。今天心里有点不高兴! 。就这样晚安~&下载地址:/data/285709本文出自 “” 博客,请务必保留此出处&&&&&
TA的最新馆藏[转]&引用 Getting Started with Web Audio API
Introduction
Audio on the web has been fairly primitive up to this point and until very recently has had to be delivered through plugins such as Flash and QuickTime. The introduction of the audio element in HTML5 is very important, allowing for basic streaming audio playback. But, it is not powerful enough to handle more complex audio applications. For sophisticated web-based games or interactive applications, another solution is required. It is a goal of this specification to include the capabilities found in modern game audio engines as well as some of the mixing, processing, and filtering tasks that are found in modern desktop audio production applications.
在网络上的音频已经相当普遍的时代,但直到最近我们想听音频,不得不通过如Flash和QuickTime的插件播放。在HTML5音频元素的引入是非常重要的,音频元素允许基本的流式音频播放。但是,它无法处理更复杂的音频应用。对于复杂的基于Web的游戏或交互式应用,另一种解决方案是必需的。这是本说明书的目的,包括在现代游戏音频引擎音频混合处理,现代桌面音频制作应用程序所包含的处理和过滤任务。
The APIs have been designed with a wide variety of use cases in mind. Ideally, it should be able to support any use case which could reasonably be implemented with an optimized C++ engine controlled via JavaScript and run in a browser. That said, modern desktop audio software can have very advanced capabilities, some of which would be difficult or impossible to build with this system. Apple's Logic Audio is one such application which has support for external MIDI controllers, arbitrary plugin audio effects and synthesizers, highly optimized direct-to-disk audio file reading/writing, tightly integrated time-stretching, and so on. Nevertheless, the proposed system will be quite capable of supporting a large range of reasonably complex games and interactive applications, including musical ones. And it can be a very good complement to the more advanced graphics features offered by WebGL. The API has been designed so that more advanced capabilities can be added at a later time.
这些API已经设计可以满足各种各样的使用案例。理想的是,它应该能够支持任何使用情况下它可以合理地具有优化C ++引擎通过JavaScript控制并在浏览器中运行来实现。这就是说,现代台式音频软件可以有非常高级的功能,其中的一些将难以或不可能建立与该系统。苹果公司的Logic音频就是这样一个应用程序,它具有外部MIDI控制器,任意插件音频效果和合成,高度优化的直接到磁盘的音频文件读取/写入,支持紧密集成的时间伸缩,等等。尽管如此,所提出的系统将是相当能够支持大范围的相当复杂的游戏和交互式应用程序,包括音乐的。它可以是一个很好的补充,通过WebGL的提供更先进的图形功能。该API被设计成使更高级的功能可以在以后的时间被加入。
The API supports these primary features:
Modular routing for simple or complex mixing/effect architectures,
including multiple sends and submixes.
High dynamic range, using 32bits floats for internal processing.
Sample-accurate scheduled sound playback with low latency for musical
applications requiring a very high degree of rhythmic precision such
as drum machines and sequencers. This also includes the possibility
of dynamic creation of effects.
模块化路由简单或复杂的混合/效果架构,包括多个发送和子混音。
高动态范围,采用32bits floats进行内部处理。
采样精确定时播放的声音与音乐的低延迟
需要的节奏等精密程度非常高的应用 作为鼓机和定序。 这也包括了可能性动态创建的效果。
Automation of audio parameters for envelopes, fade-ins / fade-outs,
granular effects, filter sweeps, LFOs etc.
Flexible handling of channels in an audio stream, allowing them to be
split and merged.
Processing of audio sources from an audio or video media element.
自动化音频参数信封,淡入/淡出,颗粒效果,过滤器扫描,低频振荡器等。
灵活的处理在音频流的信道,使它们成为拆分和合并。
处理从音频或视频的媒体元素的音频源。
Processing live audio input using a MediaStream from getUserMedia().
Integration with WebRTC Processing audio received from a remote peer
using a MediaStreamAudioSourceNode and [webrtc].
Sending a generated or processed audio stream to a remote peer using
a MediaStreamAudioDestinationNode and [webrtc].
Audio stream synthesis and processing directly in JavaScript.
使用MediaStream的getUserMedia()方法处理现场音频输入。使用MediaStreamAudioSourceNode和[WebRTC],以实现将WebRTC从远程对等体接收的音频处理整合
利用发送生成或处理的音频流发送到远程对等 一个MediaStreamAudioDestinationNode和[WebRTC]。
在JavaScript中直接处理音频流合成和加工。
Spatialized audio supporting a wide range of 3D games and immersive environments:
Panning models: equalpower, HRTF, pass-through
Distance Attenuation
Sound Cones
Obstruction / Occlusion
Doppler Shift
Source / Listener based
A convolution engine for a wide range of linear effects, especially very high-quality room effects. Here are some examples of possible effects:
Small / large room
Concert hall
Amphitheater
Sound of a distant room through a doorway
Extreme filters
Strange backwards effects
Extreme comb filter effects
Dynamics compression for overall control and sweetening of the mix
Efficient real-time time-domain and frequency analysis / music visualizer support
Efficient biquad filters for lowpass, highpass, and other common filters.
A Waveshaping effect for distortion and other non-linear effects
Oscillators
立体音效支持多种3D游戏和沉浸式环境
卷积引擎广泛的非线性效应,特别是非常高品质的室内效果。
动态压缩混合的总体控制和甜味剂
高效的实时的时域和频分析/音乐可视化支持
高效双二阶滤波器的低通,高通,和其他常用的过滤器
失真等非线性效应整波效应
Modular Routing
Modular routing allows arbitrary connections between different AudioNode objects. Each node can have inputs and/or outputs. A source node has no inputs and a single output. A destination node has one input and no outputs, the most common example being AudioDestinationNode the final destination to the audio hardware. Other nodes such as filters can be placed between the source and destination nodes. The developer doesn't have to worry about low-level stream format details when two objects ar the right thing just happens. For example, if a mono audio stream is connected to a stereo input it should just mix to left and right channels appropriately.
模块化路由允许不同的对象AudioNode之间的任意连接。每个节点可以具有输入和/或输出。源节点没有输入和一个输出。目的节点有一个输入和没有输出,最常见的例子是AudioDestinationNode最终目的地到音频硬件。如过滤器的其他节点可以放置在源和目的地节点之间。开发人员不必担心低级别的流格式的细节时,两个物体连接在一起;正确的事情只是发生。例如,如果一个单声道的音频流被连接到立体声输入应该只是混合到左和右声道适当。
In the simplest case, a single source can be routed directly to the output. All routing occurs within an AudioContext containing a single AudioDestinationNode:
在最简单的情况下,单个源可直接路由到输出。所有的路由时包含一个AudioDestinationNode的AudioContext内
AudioContext
一个AudioContext是用于管理和播放所有的声音。为了生产使用Web音频API声音,创建一个或多个声源,并将它们连接到由所提供的声音目的地AudioContext 实例。这方面并不需要是直接的,并且可以通过任何数量的中间的AudioNodes充当用于音频信号处理的模块。
AudioContext的单个实例可以支持多个声音输入和复杂的音频图表,所以我们只需要其中的一个,因为我们创建的每一个音频应用程序。许多有趣的网络音频API的功能,如创建AudioNodes和音频文件数据进行解码的AudioContext的方法
下面的代码片段创建了一个AudioContext:
window.addEventListener('load', init, false);
function init() {
// Fix up for prefixing
window.AudioContext = window.AudioContext||window.webkitAudioC
context = new AudioContext();
catch(e) {
alert('Web Audio API is not supported in this browser');
Loading sounds
网络音频API使用AudioBuffer用于中短长度的声音。其基本方法是使用XMLHttpRequest进行提取声音文件。 API支持加载多种格式的音频文件数据,如WAV,MP3,AAC,OGG等。针对不同的音频格式支持的浏览器有所不同。
var dogBarkingBuffer =
// Fix up prefixing
window.AudioContext = window.AudioContext || window.webkitAudioC
var context = new AudioContext();
function loadDogSound(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function() {
context.decodeAudioData(request.response, function(buffer) {
dogBarkingBuffer =
}, onError);
request.send();
音频文件数据为二进制(非文本),所以我们设置要求responseType是“arraybuffer”。有关ArrayBuffers的更多信息,一旦(未译码)的音频文件数据已被接收,则可以保持左右购买解码,或者它可被解码马上使用AudioContext decodeAudioData()方法。这种方法需要存储在request.response音频文件数据的ArrayBuffer并异步进行解码(不阻塞主JavaScript的执行线程)。 当decodeAudioData()完成后,它调用的回调函数,它提供解码PCM音频数据作为AudioBuffer。
一旦被加载一个或多个AudioBuffers,那么我们就可以播放声音。让我们假设我们刚刚加载的AudioBuffer有狗叫的声音,并且已完成加载过程。然后我们就可以玩这个缓冲区用下面的代码。
// Fix up prefixing
window.AudioContext = window.AudioContext || window.webkitAudioC
var context = new AudioContext();
function playSound(buffer) {
var source = context.createBufferSource(); // creates a sound source
source.buffer =
// tell the source which sound to play
source.connect(context.destination);
// connect the source to the context's destination (the speakers)
source.start(0);
// play the source now
// note: on older systems, may have to use deprecated noteOn(time);
Dealing with time: playing sounds with rhythm
网络音频API允许开发者精确安排播放。为了证明这一点,让我们建立一个简单的节奏轨道。其中hihat是发挥每一个八分音符,又踢又网罗玩法交替每季度,在4/4的时间。 假设我们已经加载了踢,圈套和hihat缓冲区,要做到这一点的代码很简单:
for (var bar = 0; bar & 2; bar++) {
var time = startTime + bar * 8 * eighthNoteT
// Play the bass (kick) drum on beats 1, 5
playSound(kick, time);
playSound(kick, time + 4 * eighthNoteTime);
// Play the snare drum on beats 3, 7
playSound(snare, time + 2 * eighthNoteTime);
playSound(snare, time + 6 * eighthNoteTime);
// Play the hi-hat every eighth note.
for (var i = 0; i & 8; ++i) {
playSound(hihat, time + i * eighthNoteTime);
不要轻易尝试 那画面太美 我不敢直视
Changing the volume of a sound
一,你可能想要做一个声音的最基本的操作是改变它的音量。通过GainNode才能使用Web API的音频,我们可以路由我们的源到目的地操纵量:
此连接建立可以实现如下:
// Create a gain node.
var gainNode = context.createGain();
// Connect the source to the gain node.
source.connect(gainNode);
// Connect the gain node to the destination.
gainNode.connect(context.destination);
经过图已经成立,你可以通过编程操纵gainNode.gain.value如下改变音量:
// Reduce the volume.
gainNode.gain.value = 0.5;
你们试下调个几千倍 那场面不敢直视
Cross-fading between two sounds
现在,假设我们有一个稍微复杂的情况,我们正在玩多种声音,但要跨越二者之间褪色。这是在一个DJ状的应用,其中,我们有两个唱盘和希望能够从一个声源到平移到另一种常见的情况。要使用这样的功能设置此,我们简单地创建两个GainNodes,并通过连接节点每个源
function createSource(buffer) {
var source = context.createBufferSource();
// Create a gain node.
var gainNode = context.createGain();
source.buffer =
// Turn on looping.
source.loop =
// Connect source to gain.
source.connect(gainNode);
// Connect gain to destination.
gainNode.connect(context.destination);
source: source,
gainNode: gainNode
Equal power crossfading
一个天真的线性淡入淡出的方式表现出你的样本之间平移量畅游。
为了解决这一问题,我们使用一个等功率曲线,其中所述相应增益曲线是非线性的,并相交以更高的幅度。这最大限度地减少体积骤降音频区域之间,从而导致更均匀的交叉衰减,可能是在电平略有不同区域之间。
Playlist crossfading
另一种常见的平滑转换应用是一个音乐播放器应用。当一首歌曲的变化,我们希望在淡出当前曲目了,褪去了新的,避免了不和谐的过渡。要做到这一点,安排交叉淡入淡出的未来。虽然我们可以使用的setTimeout执行此调度,这是不准确的。随着Web API的音频,我们可以使用AudioParam界面安排为参数的未来值,如GainNode的增益值。 因此,给定播放列表,我们可以轨道之间通过调度当前播放的曲目上的增益下降,并在接下来的一个增益提高升学,双双小幅之前,当前曲目播放结束:
function playHelper(bufferNow, bufferLater) {
var playNow = createSource(bufferNow);
var source = playNow.
var gainNode = playNow.gainN
var duration = bufferNow.
var currTime = context.currentT
// Fade the playNow track in.
gainNode.gain.linearRampToValueAtTime(0, currTime);
gainNode.gain.linearRampToValueAtTime(1, currTime + ctx.FADE_TIME);
// Play the playNow track.
source.start(0);
// At the end of the track, fade it out.
gainNode.gain.linearRampToValueAtTime(1, currTime + duration-ctx.FADE_TIME);
gainNode.gain.linearRampToValueAtTime(0, currTime + duration);
// Schedule a recursive track change with the tracks swapped.
var recurse = arguments.
ctx.timer = setTimeout(function() {
recurse(bufferLater, bufferNow);
}, (duration - ctx.FADE_TIME) * 1000);
Applying a simple filter effect to a sound
该网络音频API允许从一个音频节点到另一个你管的声音,创造一个潜在的复杂的处理器链复杂的效果添加到您的soundforms。 这样做的一个方法是把你的声源和目的地之间BiquadFilterNodes。这种类型的音频节点可以做各种的可用于构建图形均衡器,甚至更复杂的效果,主要是为了做选择其中的声音的频谱的部分强调并制服低阶滤波器。支持的类型的过滤器包括:
Low pass filter
High pass filter
Band pass filter
Low shelf filter
High shelf filter
Peaking filter
Notch filter
All pass filter
和所有的过滤器所包含的参数,指定一定量的增益,在该应用过滤器的频率和品质因数。低通滤波器保持较低的频率范围,但丢弃高频。折断点由频率值确定,并且Q因子是无单位,并确定该图的形状。增益只影响特定的过滤器,如低货架和峰值滤波器,而不是本低通滤波器。
在一般情况下,频率控制需要进行调整工作在对数标度,因为人的听觉本身的工作原理相同(即,A 4为440Hz的,和A5是880hz)。欲了解更多详细信息,请参阅上面的源代码链接FilterSample.changeFrequency功能。 最后,请注意,示例代码,您可以连接和断开滤波器,动态变化的AudioContext图。我们可以通过调用node.disconnect(outputNumber)断开图AudioNodes。例如,要重新路线图从去通过一个过滤器,以直接连接,我们可以做到以下几点:
// Disconnect the source and filter.
source.disconnect(0);
filter.disconnect(0);
// Connect the source directly.
source.connect(context.destination);
你可能感兴趣的文章
1 收藏,633
3 收藏,681
8 收藏,846
哥们,你的翻译实在辣眼睛啊
分享到微博?
你好!看起来你挺喜欢这个内容,但是你还没有注册帐号。 当你创建了帐号,我们能准确地追踪你关注的问题,在有新答案或内容的时候收到网页和邮件通知。还能直接向作者咨询更多细节。如果上面的内容有帮助,记得点赞 (????)? 表示感谢。
明天提醒我
我要该,理由是:
扫扫下载 App在一个GameObject上进行多个AudioSource的控制
时间: 15:08:46
&&&& 阅读:137
&&&& 评论:
&&&& 收藏:0
标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&
/demo_c161_i105215.html?qqdrsign=03f8c
using&UnityE&&
using&System.C&&
public&class&SoundSwitch&:&MonoBehaviour&{&&
&&&&public&AudioSource&as1;&&
&&&&public&AudioSource&as2;&&
&&&&public&AudioClip[]&a1;&&
&&&&void&Start&()&{&&
&&&&this.gameObject.AddComponent("AudioSource");&&
&&&&this.gameObject.AddComponent("AudioSource");&&
&&&&var&as_array=this.gameObject.GetComponents(typeof(AudioSource));&&
&&&&as1=(AudioSource)as_array[0];&&
&&&&as2=(AudioSource)as_array[1];&&
&&&&as1.clip=a1[1];&&
&&&&as2.clip=a1[2];&&
&&&&AudioPlay();&&
&&&&void&Update&()&{&&
&&&&void&AudioPlay()&&
&&&&&&&&as2.Play();&&
&&&&&&&&as1.Play();&&
http://www.codefans.net/articles/1334.shtml
这是我收集的一个由C#编写的音乐播放器的主Form代码,觉得里面有一些小技巧还是不错的,特此发给大家。里面有播放器背景设置、线程定义、调用读取文件目录方法、播放时间计数器、设置LV背景、获取播放歌曲、播放按钮,切换播放or暂停、切换歌曲到下一首,调用切歌方法、显示播放列表、歌词局中、播放窗体最小化隐藏到托盘设置、进度条滚动模块、从歌曲列表中删除文件等。
using System.Collections.G
using ponentM
using System.D
using System.D
using System.L
using System.T
using System.Windows.F
using System.IO;
using System.Drawing.I
using System.T
namespace MyMusicBox
public partial class MainForm : Form
public MainForm()
InitializeComponent();
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
Song mySong = null;//播放的歌曲对象
ListViewItem itemL//打开歌词路径项
B//用于动态设置LV背景
public SavingInfo sa = null;//持久化信息类
T//后台线程
#region 加载事件
private void MainForm_Load(object sender, EventArgs e)
//调用读取配置文件方法
Path.ReadPath();
//窗体背景设置为配置文件中的图片
this.BackgroundImage = Image.FromFile(Path.bgPath);
//调用读取文件目录方法
Path.ReadSong();
//读取播放列表
sa = new SavingInfo();
sa.LoadPlayList();
BindAllLV();
BindPlayLV();
SetLrcBG();
timer1.Enabled = Path.P
//显示时间
lblTime.Text = System.DateTime.Now.ToString();
//两个lbl用来根据歌曲总长和播放长度显示进度,设置位置重叠
lblRuning.Location = lblLong.L
//启动线程
thread = new Thread(Renovate);
thread.IsBackground = true;
thread.Start();
#endregion
#region 后台刷新
/// &summary&
/// 时间计数状态等刷新
/// &/summary&
private void Renovate()
//while (true)
//获取当前时间
lblTime.Text = System.DateTime.Now.ToString();
//无歌曲提示,如果播放列表为空且当前播放列表为显示状态
if (lvPlay.Items.Count == 0 && lvPlay.Visible)
lblTs.Visible =
lblTs.Visible =
Thread.Sleep(1000);
#endregion
#region 设置LV背景
/// &summary&
/// 设置LV背景
/// &/summary&
public void SetLV()
bm = new Bitmap(this.BackgroundImage, this.Width, this.Height);
//绘制矩形,定义起始位置和宽高
Rectangle r = new Rectangle(lvPlay.Location.X, lvPlay.Location.Y, lvPlay.Width, lvSong.Height);
//按矩形尺寸和起始位置截取bm的一部分
bm= bm.Clone(r,bm.PixelFormat);
//把截取到的图片设置为lv背景,达到与主窗体背景完美契合的效果
lvSong.BeginUpdate();
lvSong.BackgroundImage = (Image)
lvSong.EndUpdate();
lvPlay.BeginUpdate();
lvPlay.BackgroundImage = (Image)
lvPlay.EndUpdate();
#endregion
#region 获取歌曲
/// &summary&
/// 获取播放歌曲
/// &/summary&
private void GetSong()
//接收播放歌曲方法,获得一个歌曲对象
this.mySong = PlayList.Play();
//如果歌曲对象不为空
if (mySong != null)
//播放器路径设置为该歌曲路径
wmp.URL = mySong.FileN
//调用方法,显示歌曲名、歌手
lblName.Text = PlayList.GetName();
lblSinger.Text = PlayList.GetSinger();
mySong.SongState = SongPlayState.//修改播放状态
//播放按钮图片修改为暂停图片
btnPlay.Image = Image.FromFile("Images\\stop.png");
//读取歌词路径
Path.ReadLrc();
//启动一个定时器,此定时器只控制歌词轮播
timer2.Start();
catch (Exception)
LrcNull();
itemLrc = new ListViewItem();
itemLrc.SubItems.Add("找不到该歌曲歌词文件!");
itemLrc.ForeColor = Color.B
itemLrc.Font = new Font("微软雅黑", 14.25F, ((FontStyle)((FontStyle.Bold | FontStyle.Underline))), GraphicsUnit.Point, ((byte)(134)));
lvLrc.Items.Add(itemLrc);
#endregion
#region 主定时器
private void timer1_Tick(object sender, EventArgs e)
if (Path.songPath == "")
timer1.Enabled = false;
//如果当前无播放歌曲,调用获取歌曲的方法
if (this.mySong == null)
GetSong();
//自动下一首,如果当前播放完毕
if (this.wmp.playState == WMPLib.WMPPlayState.wmppsStopped)
this.mySong = null; // 将歌曲设为空
Path.lrcPath = "";
Path.dicLrc.Clear();
PlayModel();
PlayList.PlayNext();
Thread.Sleep(1000);
// 切歌,当前有播放歌曲且播放状态为cut
if (this.mySong != null && this.mySong.SongState == SongPlayState.cut)
this.wmp.URL = "";//置空
timer2.Stop();
Path.dicLrc.Clear();
Path.lrcPath = "";
this.mySong = null;
//如果当前有播放歌曲,需要获取的一些属性
if (wmp.URL!="")
//设置当前播放歌曲颜色
SongColor();
//获取音量控件显示值,根据控制刻度数量计算
this.trackBar1.Value = wmp.settings.volume / 10;
//歌曲时间显示,一个是总长度,一个是已播放长度,字符串类型
lblAll.Text = wmp.currentMedia.durationS
lblRun.Text = wmp.Ctlcontrols.currentPositionS
//进度条,使用了两个lbl控件,歌曲长度/已播放长度=lbl1的宽/lbl2的宽
//乘1000为防止数据过小出现错误
double temp = (wmp.currentMedia.duration*1000) / (wmp.Ctlcontrols.currentPosition*1000);
double width = lblLong.W
double avg = width /
//判断&1为了防止avg数值小于int界限
lblRuning.Width = Convert.ToInt32(avg);
picRun.Left = lblRuning.R
//托盘显示播放歌曲
this.notifyIcon1.Text =lblName.Text
+ lblSinger.T
#endregion
#region 播放按钮
/// &summary&
/// 播放按钮,切换播放or暂停
/// &/summary&
private void btnPlay_Click(object sender, EventArgs e)
if(!timer1.Enabled)
timer1.Start();
//如果当前为正在播放
if (wmp.playState == WMPLib.WMPPlayState.wmppsPlaying)
//暂停播放
wmp.Ctlcontrols.pause();
//按钮图片修改为播放
btnPlay.Image = Image.FromFile("Images\\play.png");
//停止控制歌词滚动的定时器
if (timer2.Enabled)
timer2.Stop();
else if (wmp.playState == WMPLib.WMPPlayState.wmppsPaused)
//开始播放
wmp.Ctlcontrols.play();
//按钮图片修改为暂停
btnPlay.Image = Image.FromFile("Images\\stop.png");
//启动歌词滚动
if (!timer2.Enabled&&Path.dicLrc.Count&0)
timer2.Start();
#endregion
#region 切歌
//切换下一首,调用切歌方法
private void btnRight_Click(object sender, EventArgs e)
PlayList.Cut(false);
//上一首,调用切歌方法
private void btnLeft_Click(object sender, EventArgs e)
PlayList.Cut(true);
#endregion
#region 音量
//静音,静音!=音量为0
private void btnModel_Click(object sender, EventArgs e)
//如果播放器非静音状态,前景文字显示红叉,状态改为静音
if (wmp.settings.mute == false)
btnSound.Text = "&";
wmp.settings.mute = true;
else//反之,已是静音状态,清空红叉,设置非静音状态
btnSound.Text = "";
wmp.settings.mute = false;
//设置音量,此事件为控制刻度值变化时
private void trackBar1_Scroll(object sender, EventArgs e)
//音量设置为控制刻度*10(因为初始化的时候是/10)
wmp.settings.volume = this.trackBar1.Value * 10;
#endregion
#region 歌曲列表操作
/// &summary&
/// 绑定所有歌曲LV数据
/// &/summary&
private void BindAllLV()
//如果所有歌曲集合为空,结束
if (PlayList.song == null)
lvSong.Items.Clear();
//遍历集合绑定到所有歌曲LV
foreach (Song s in PlayList.song)
ListViewItem item = new ListViewItem(s.Name);
item.Tag =
item.SubItems.Add(s.Singer);
lvSong.Items.Add(item);
//点击显示所有歌曲
private void tslblAll_Click(object sender, EventArgs e)
//隐藏播放列表
lvPlay.Visible = false;
//两个LV位置重叠
lvSong.Location = lvPlay.L
//点击后改变背景色
tslblAll.BackColor = Color.S
tslblPlay.BackColor = Color.T
//显示所有歌曲LV
lvSong.Visible = true;
//点击显示播放列表
private void tslblPlay_Click(object sender, EventArgs e)
//调用绑定播放LV数据
BindPlayLV();
//背景色改变
tslblPlay.BackColor = Color.S
tslblAll.BackColor = Color.T
//隐藏所有歌曲LV
lvSong.Visible = false;
//显示播放LV
lvPlay.Visible = true;
/// &summary&
/// 绑定播放列表
/// &/summary&
private void BindPlayLV()
//如果播放集合不为空
if (PlayList.play!=null)
lvPlay.Items.Clear();
//遍历集合绑定播放LV
foreach (Song s in PlayList.play)
int id = lvPlay.Items.Count + 1;
ListViewItem item = new ListViewItem(id.ToString());
item.SubItems.Add(s.Name);
item.Tag =
lvPlay.Items.Add(item);
/// &summary&
/// 歌曲计数
/// &/summary&
private void Count()
//if (lvSong.Visible)
lblCount.Text = "已选" + lvSong.CheckedItems.Count + "\\总" + lvSong.Items.C
//if (lvPlay.Visible)
lblCount.Text = "总" + lvPlay.Items.C
#endregion
#region 歌词操作
/// &summary&
/// 设置歌词背景
/// &/summary&
public void SetLrcBG()
bm = new Bitmap(this.BackgroundImage, this.Width, this.Height);
//绘制矩形,定义起始位置和宽高
Rectangle r = new Rectangle(lvLrc.Location.X, lvLrc.Location.Y, lvLrc.Width, lvLrc.Height);
//按矩形尺寸和起始位置截取bm的一部分
bm = bm.Clone(r, PixelFormat.Undefined);
//把截取到的图片设置为lv背景,达到与主窗体背景完美契合的效果
lvLrc.BeginUpdate();
lvLrc.BackgroundImage = (Image)
lvLrc.EndUpdate();
int nullC//记录空行位置
/// &summary&
/// 设置空行,使歌词局中
/// &/summary&
private void LrcNull()
lvLrc.Items.Clear();
nullCount = (int)Math.Ceiling(Convert.ToDouble(lvLrc.Height / 30 / 2));
for (int i = 0; i &= nullC i++)
lvLrc.Items.Add("");
/// &summary&
/// 添加歌词
/// &/summary&
private void AddLrc()
LrcNull();
foreach (string key in Path.dicLrc.Keys)
ListViewItem item = new ListViewItem();
item.SubItems.Add(Path.dicLrc[key]);
item.Tag =
lvLrc.Items.Add(item);
//只控制歌词轮播
private void timer2_Tick(object sender, EventArgs e)
//调用显示歌词的方法
ShowLrc();
/// &summary&
/// 显示歌词
/// &/summary&
private void ShowLrc()
foreach (ListViewItem item in lvLrc.Items)
if (item.Tag == null)
if (item.Tag.ToString() == lblRun.Text )
item.ForeColor = Color.DarkO
item.Font = new Font("华文琥珀", 16F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(134)));
lvLrc.Items[item.Index -1].ForeColor = Color.S
lvLrc.Items[item.Index - 1].Font = new Font("微软雅黑", 12F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(134)));
if (item.Index + 1&lvLrc.Items.Count)
lvLrc.Items[item.Index+1].EnsureVisible();
#endregion
窗体隐藏到托盘设置
//最小化到托盘
private void btnMix_Click(object sender, EventArgs e)
this.Hide();
//主窗体大小状态变化时
private void MainForm_SizeChanged(object sender, EventArgs e)
if (this.WindowState == FormWindowState.Minimized)
//启动一个控件,该控制可以让程序在右下角显示图标,需要提前设置该控制显示的图标图片
this.notifyIcon1.Visible = true;
//托盘显示,双击显示窗体
private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
ShowMain();
/// &summary&
/// 显示主窗体
/// &/summary&
public void ShowMain()
if (!this.Visible)
this.TopMost = true;
this.Show();
this.TopMost = false;
this.TopMost = true;
this.TopMost = false;
//托盘打开窗体
private void tsmiShow_Click(object sender, EventArgs e)
ShowMain();
//托盘退出
private void tsmiExit_Click(object sender, EventArgs e)
Application.Exit();
#endregion
Point mouseO//鼠标移动位置变量
bool leftF//标记是否为左键
private void pnlMain_MouseDown(object sender, MouseEventArgs e)
if (e.Button == MouseButtons.Left)
mouseOff = new Point(-e.X, -e.Y); //得到变量的值
leftFlag = true; //点击左键按下时标注为
private void pnlMain_MouseMove(object sender, MouseEventArgs e)
if (leftFlag)
Point mouseSet = Control.MouseP
mouseSet.Offset(mouseOff.X, mouseOff.Y); //设置移动后的位置
Location = mouseS
private void pnlMain_MouseUp(object sender, MouseEventArgs e)
if (leftFlag)
leftFlag = false;//释放鼠标后标注为
#endregion
#region 进度条滚动块移动
int runX;//记录滚动块初始位置
private void picRun_MouseDown(object sender, MouseEventArgs e)
runX = e.X;
//释放鼠标位移,进度前进
private void picRun_MouseUp(object sender, MouseEventArgs e)
picRun.Left += e.X - runX - picRun.Width / 2;
if (picRun.Left & lblLong.Right)
picRun.Left = lblLong.R
if(picRun.Left&lblLong.Left)
picRun.Left = lblLong.L
if (mySong != null)
lblRuning.Width = picRun.Right- lblRuning.L
double temp = (lblLong.Width*1000.0 )/ (lblRuning.Width*1000.0);
wmp.Ctlcontrols.currentPosition = wmp.currentMedia.duration /
#endregion
#region 歌曲增删操作
//添加歌曲到播放列表
private void tsmiAdd_Click(object sender, EventArgs e)
if (lvSong.CheckedItems.Count & 0)
foreach (ListViewItem item in lvSong.CheckedItems)
// 遍历播放集合,如果存在不添加
foreach (Song s in PlayList.play)
if (s.Name == item.Text)
PlayList.play.Remove(s);
PlayList.play.Add(item.Tag as Song);
//所有歌曲:删除选中歌曲
private void tsmiDel_Click(object sender, EventArgs e)
foreach (ListViewItem item in lvSong.Items)
if (item.Checked)
PlayList.song.Remove(item.Tag as Song);
BindAllLV();
//全选歌曲
private void tsmiCheck_Click(object sender, EventArgs e)
foreach (ListViewItem item in lvSong.Items)
if (tsmiCheck.Text == "全部选中")
item.Checked = true;
if(item.Index+1==lvSong.Items.Count)
tsmiCheck.Text = "取消选中";
item.Checked = false;
if (item.Index + 1 == lvSong.Items.Count)
tsmiCheck.Text = "全部选中";
//选中项的同时选中复选框
private void lvSong_MouseDown(object sender, MouseEventArgs e)
if (lvSong.SelectedItems.Count & 0 && e.Button == MouseButtons.Left)
lvSong.SelectedItems[0].Checked = true;
//播放列表删除事件
private void tsmiPlayDel_Click(object sender, EventArgs e)
foreach (ListViewItem item in lvPlay.Items)
if (item.Selected)
//PlayList.id = (lvPlay.Items[item.Index+1].Tag as Song).Id;
//this.song =
PlayList.play.Remove(item.Tag as Song);
BindPlayLV();
//清空播放列表
private void tsmiPlayClear_Click(object sender, EventArgs e)
PlayList.play.Clear();
this.mySong = null;
BindPlayLV();
//从播放列表删除文件
private void tsmiPlayDelFile_Click(object sender, EventArgs e)
if (lvPlay.SelectedItems.Count & 0)
DelFile(lvPlay.SelectedItems[0]);
/// &summary&
/// 删除某项对应文件
/// &/summary&
/// &param name="item"&&/param&
private void DelFile(ListViewItem item)
string path = (item.Tag as Song).FileN
File.Delete(path);
BindAllLV();
BindPlayLV();
catch (Exception)
MessageBox.Show("该文件为只读文件或用户权限不够,无法删除!");
//从所有歌曲中删除文件
private void tsmiDelFile_Click(object sender, EventArgs e)
if (lvSong.SelectedItems.Count & 0)
DelFile(lvSong.SelectedItems[0]);
//双击列表项播放歌曲
private void lvPlay_DoubleClick(object sender, EventArgs e)
if (!timer1.Enabled)
PlayList.id = (lvPlay.SelectedItems[0].Tag as Song).Id;
timer1.Start();
if (lvPlay.SelectedItems.Count & 0)
PlayList.id = (lvPlay.SelectedItems[0].Tag as Song).Id;
this.mySong = null;
#endregion
#region 设置
//跳转设置窗体
private void btnSet_Click(object sender, EventArgs e)
SetForm set = new SetForm();
set.parent = this;//把主窗体传过去
set.Show(this);
#endregion
#region 回滚
/// &summary&
/// 路径重置后
/// &/summary&
public void Back()
BindAllLV();
PlayList.Update();
timer1.Start();
#endregion
#region 退出
//关闭时保存列表
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
if (Path.SaveList)
sa.SavePlayList();
//面板退出
private void btnExit_Click(object sender, EventArgs e)
if (Path.Exit)
Application.Exit();
this.Hide();
#endregion
#region 背景颜色等变换控制
private void btnLeft_MouseEnter(object sender, EventArgs e)
((Button)sender).BackgroundImage = Image.FromFile("Images//allbtn_highlight.png");
private void btnLeft_MouseLeave(object sender, EventArgs e)
((Button)sender).BackgroundImage = null;
private void tslblPlay_MouseEnter(object sender, EventArgs e)
((ToolStripLabel)sender).BackgroundImage = Image.FromFile("Images//Album_bkg_wubian.png");
private void tslblPlay_MouseLeave(object sender, EventArgs e)
((ToolStripLabel)sender).BackgroundImage = null;
//选中改变颜色
private void lvSong_ItemChecked(object sender, ItemCheckedEventArgs e)
foreach (ListViewItem item in lvSong.Items)
if (item.Checked)
item.ForeColor = Color.DarkO
item.ForeColor = Color.DimG
/// &summary&
/// 当前播放歌曲改变颜色
/// &/summary&
private void SongColor()
foreach (ListViewItem item in lvPlay.Items)
if (item.SubItems[1].Text == lblName.Text)
item.ForeColor = Color.DeepSkyB
item.ForeColor = Color.W
#endregion
#region 选择歌词
private void lvLrc_MouseDown(object sender, MouseEventArgs e)
if (lvLrc.SelectedItems.Count&0&&lvLrc.SelectedItems[0] == itemLrc)
if (Path.OpenLrc())
//启动一个定时器,此定时器只控制歌词轮播
timer2.Start();
#endregion
#region 窗体最大化设置
S//原始尺寸
Point pN;//原始位置
private void btnMax_Click(object sender, EventArgs e)
Size max = new Size(Screen.PrimaryScreen.WorkingArea.Width - 10, Screen.PrimaryScreen.WorkingArea.Height - 20);
if (this.Size != max)
pN = this.L
now= this.S
this.Size =
this.Left = 5;
this.Top = 5;
btnMax.Image = Image.FromFile("Images//max1.png")
this.Location = pN;
this.Size =
btnMax.Image = Image.FromFile("Images//max.png");
SetLrcBG();
#endregion
#region 歌词、MV切换
private void tsmiLrc_Click(object sender, EventArgs e)
lvLrc.Visible = true;
wmp.Visible = false;
tsmiLrc.BackColor = Color.LawnG
tsmiMv.BackColor = Color.T
private void tsmiMv_Click(object sender, EventArgs e)
wmp.Location = lvLrc.L
wmp.Size = lvLrc.S
lvLrc.Visible = false;
wmp.Visible = true;
tsmiLrc.BackColor = Color.T
tsmiMv.BackColor = Color.LawnG
#endregion
#region 播放模式切换
/// &summary&
/// 播放模式
/// &/summary&
private void PlayModel()
if (tsmiOne.Checked)
PlayList.PlayOne();
else if (tsmiSJ.Checked)
PlayList.PlayRandom();
private void tsmiXH_Click(object sender, EventArgs e)
ToolStripMenuItem ts=((ToolStripMenuItem)sender);
foreach(ToolStripMenuItem item in tsmiModel.DropDownItems)
if (ts.Checked && ts == item)
item.Checked = false;
#endregion
&标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&原文:/lfy007/p/4816342.html
教程昨日排行
&&国之画&&&& &&&&&&
&& &&&&&&&&&&&&&&
鲁ICP备号-4
打开技术之扣,分享程序人生!}

我要回帖

更多关于 setaudiosource 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信