⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 internetmusic.java

📁 Java多线程实现的显示波形的Applet高级播放器
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
	        Thread playThread;
		//启动线程播放音乐
	        public void startPlay(){
        		playThread = new Thread(this);
	        	playThread.start();
        	}
		//关闭线程,停止播放音乐。
        	public void stopPlay(){
            		playThread = null;
       		}
		//实现Runnable接口方法
		public void run(){

			try{
				//重新取得audioInputStram,以免被waveGraphPane.drawWaveLine(null).
				audioInputStream=AudioSystem.getAudioInputStream(url);
			}catch(Exception e){System.out.println(e);}




			if(audioInputStream==null){ //没有播放的音乐
				playThread=null;
				return;
			}
	/*		try{ //对输入流进行复位到上次标记位置,准备继续播放。
                		audioInputStream.reset();
            		} catch(IOException e){
                		System.out.println("复位失败"+e.toString());
				playThread=null;
				return;
			}*/
	
        		//检查是否支持DataLine
			audioFormat=audioInputStream.getFormat();
        		DataLine.Info info = new DataLine.Info(SourceDataLine.class,audioFormat);
	        	if (!AudioSystem.isLineSupported(info)){
				System.out.println("不支持DataLine");
				playThread=null;
		                return;
			}
			//打开SourceDataLine
			try {
				sdLine=(SourceDataLine)AudioSystem.getLine(info);
	                	sdLine.open(audioFormat, bufferSize);
	                } catch (LineUnavailableException e) { 
				System.out.println("不能打开SourceDataLine: "+e);
				playThread=null;
        	        	return;
            		}
			//创建一个只有半个SourceDataLine缓冲区大小的字节数组
			byte[] data=new byte[sdLine.getBufferSize()/2];
			int numBytesRead=0;
			//开始播放
			sdLine.start();
        		while (playThread != null){ 
				try{
					if((numBytesRead=audioInputStream.read(data)) == -1){//从输入流中读数据到data
						break;
					}
		                	int numBytesRemaining=numBytesRead;
        		        	while(numBytesRemaining>0){ //写入sdLine的数据队列
						numBytesRemaining-=sdLine.write(data, 0, numBytesRemaining);
                			}
		                } catch(IOException e){
					System.out.println("播放错误: "+e);
					break;
                		}
			}
	            	//播放完成或出现异常时,关闭相关资源.
		        if (playThread!=null) {
                		sdLine.drain();
            		}
		        sdLine.stop();
        		sdLine.close();
	        	sdLine=null;
	                playThread=null;
		}

	}

	//绘制音乐曲线图
	class WaveGraphPane extends JPanel implements Runnable{ 
		Thread graphThread;
        	private Font font12 = new Font("serif", Font.PLAIN, 12);
		//背景黑色
        	public WaveGraphPane() {
	            setBackground(new Color(15, 15, 15));
        	}
		//按字节数据绘制音乐曲线图
		public void drawWaveLine(byte[] audioBytes){
			lines.removeAllElements();  //清除向量元素
			if(audioBytes==null){
        	        	try{  //帧数*一帧字节数,并将long型强制转换为int,不支持太大文件的播放.
					audioFormat=audioInputStream.getFormat();
                		    	audioBytes=new byte[(int)(audioInputStream.getFrameLength()*audioFormat.getFrameSize())];
	                    		audioInputStream.read(audioBytes); //读入到audioBytes字节数组
        	       		}catch(Exception e){ 
					System.out.println(e.toString());
					repaint();
        	            		return; 
                		}
            		}
		        int w=getSize().width;
			int h=getSize().height-20;
			int[] audioData=null;//将byte数组数据转换为int数组数据,便于绘制.
			if(audioFormat.getSampleSizeInBits()==16){
        	        	int nlengthInSamples=audioBytes.length/2;
                		audioData=new int[nlengthInSamples];
                		if(audioFormat.isBigEndian()){
                			for(int i=0; i<nlengthInSamples;i++){
                        			//audioBytes偶字节HAB作高位字节处理
	                         		int HAB = (int) audioBytes[2*i];
        	                 		//audioBytes奇字节LAB作低位字节处理
                	         		int LAB = (int) audioBytes[2*i+1];
						//移位形成一个新整数
                         			audioData[i] = HAB << 8 | (255 & LAB);
                     			}
                 		}
				else{
					for (int i = 0; i < nlengthInSamples; i++) {
                	        		//audioBytes偶字节作低位字节处理
                        			int LAB = (int) audioBytes[2*i];
                        			//audioBytes奇字节作高位字节处理
                        			int HAB = (int) audioBytes[2*i+1];
	                        		audioData[i] = HAB << 8 | (255 & LAB);
					}
                	 	}
             	 	} 
			//一个象素点对应多少个帧
			int frames_per_pixel=audioBytes.length/audioFormat.getFrameSize()/w;
            		byte my_byte=0;
	            	double y_last = 0;
        	    	int numChannels=audioFormat.getChannels();
            		for (double x = 0; x < w && audioData != null; x++){
                		int idx = (int)(frames_per_pixel * numChannels * x);
	                	//双字节采样,32768是2的15次方
        	        	my_byte=(byte)(128 * audioData[idx]/32768 );
                		double y_new = (double) (h * (128 - my_byte) / 256);
                		lines.add(new Line2D.Double(x, y_last, x, y_new));
	                	y_last = y_new;
			}
                	repaint();
        	}

	        public void paint(Graphics g) {
			int w = getSize().width;
            		int h = getSize().height;
	            	int INFORECT=17; //定义一个提示信息的小矩形块高度

	            	Graphics2D g2 = (Graphics2D)g; //转换g为g2
        	    	g2.setBackground(getBackground());
            		g2.clearRect(0, 0, w, h); //清除以前曲线
	            	g2.setColor(Color.white);
        	    	g2.fillRect(0, h-INFORECT, w, INFORECT);//面板下面的一小块白色。
			//
			g2.setColor(Color.black);
                	g2.setFont(font12);
                	g2.drawString("歌曲: " + selSong + "  长度: " + 
					String.valueOf(duration) + "  位置: " +
					String.valueOf(seconds), 3, h-4);
        	        if(audioInputStream != null){
                		//绘制音乐曲线
	                	g2.setColor(Color.yellow);  //黄色音频曲线
        	            	for(int i = 1; i <lines.size(); i++){
                	        	g2.draw((Line2D)lines.get(i));
                    	    	}
                    		//绘制红线表示当前播放位置
	                	if (seconds != 0){
                        		double loc=seconds/duration*w;
	                        	g2.setColor(Color.red);
        	                	g2.setStroke(new BasicStroke(3));
                	        	g2.draw(new Line2D.Double(loc, 0, loc, h-INFORECT-2));
				}
			}
               	}
        
		public void startDraw() {
			graphThread=new Thread(this);
			graphThread.start();
			seconds=0;
        	}

	        public void stopDraw(){
			if (graphThread != null) {
				graphThread=null;
            		}	
			graphThread = null;
        	}

	        public void run(){
			seconds = 0;
	            	while (graphThread != null){
				if ((playMusic.sdLine != null) && (playMusic.sdLine.isOpen())){
			        	//播放情形,将毫秒化为秒.
					long milliseconds=(long)(playMusic.sdLine.getMicrosecondPosition()/1000);
					seconds=milliseconds/1000.0;
        		        }
				try {
					graphThread.sleep(100); 
				}catch (Exception e){ 
					break; //跳出循环
				} 
	               		repaint();
                                
        	        	while ((playMusic.sdLine != null && !playMusic.sdLine.isOpen())) 
                		{
	                  		  try { 
						graphThread.sleep(10); 
					  } catch (Exception e){
						 break; 
					  }
        	        	}
            		}
			seconds = 0;
        	    	repaint();
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -