پخش فایل های MP3 و WAV در جاوا

java-mp3-wav-wallpaper

در این بخش از آموزش برنامه نویسی جاوا قصد داریم پخش صوت با پسوند های mp3  و wav را مورد بررسی قرار دهیم برای درک و استفاده از این آموزش باید آشنایی کافی با OOP (برنامه نویسی شیء گرا) و File در جاوا داشته باشید.

آموزش را با wav شروع می کنیم.

بخش اول wav

کلاس ها و متدهای زیادی برای پخش فرمت wav در جاوا وجود دارند که ساده ترین آن ها استفاده از پکیج sun.audio است .(نیاز به اضافه کردن نیست جزء کتابخانه های استاندارد جاوا می باشد)

یک پروژه ی جاوا در NetBeans ایجاد و نامی مناسب برای آن انتخاب کنید مثلا WavPlayer. سپس متغییر های زیر را به صورت public در ابتدای کلاس (در بالای متد main ) جدید ایجاد کنید .

FileInputStream myMusic;
String filepath = null;
AudioStream audioStream = null;
Button btnPlay;
Button btnStop;

کلاس های مورد نیاز را import کنید (در ادامه متد زیر را به برنامه اضافه نمایید) همچنین توجه کنید که متد مورد نظر از نوع static نیست بنابراین موقع صدا زدن در متد main باید با شی ساخته شده از همین کلاس فراخوانی انجام شود .

 public  void Frame_main() {
        JFrame frame = new JFrame("wav player");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setLayout(null);
        frame.setResizable(false);
        frame.setSize(200, 200);
        frame.setVisible(true);
        btnPlay = new Button("play");
        btnStop = new Button("stop");
        btnPlay.setBounds(70, 35, 60, 40);
        btnStop.setBounds(70, 90, 60, 40);
        btnPlay.setBackground(Color.PINK);
        btnStop.setBackground(Color.cyan);
        frame.add(btnPlay);
        frame.add(btnStop);
    }

این متد یک محیط گرافیکی کاملا ساده همراه با سه دکمه (Button) برای play و stop و pause کردن فایل صوتی پیاده سازی شده است .

حالا در بلوک های متد main (داخل نقطه ی شروع برنامه) یک شی از کلاس که هم اکنون در آن هستیم ایجاد می کنیم دلیل ایجاد این شی static بودن متد main است. با استفاده از این شی به متدها و فیلدهای غیر static در داخل متد static میتوان دسترسی پیدا کرد ؛ با شی ایجاد شده فیلد هایی که در بالا تعریف کردیم را مقدار دهی کنید.

 public static void main(String[] args) {
        WavPlayer f = new WavPlayer();
        f.Frame_main();
        try {
            f.myMusic = new FileInputStream(new File("D:\\1.wav"));
            f.audioStream = new AudioStream(f.myMusic);
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
        }
        f.btnPlay.addActionListener((e) -> {
            if (f.audioStream == null) {
                try {
                    f.myMusic = new FileInputStream(new File("D:\\1.wav"));
                    f.audioStream = new AudioStream(f.myMusic);
                    AudioPlayer.player.start(f.audioStream);
                } catch (Exception ex) {
                    System.err.println(ex.getMessage());
                }
            } else {
                AudioPlayer.player.start(f.audioStream);
            }
        });
        f.btnStop.addActionListener((e) -> {
            if (f.audioStream != null) {
                AudioPlayer.player.stop(f.audioStream);
                f.audioStream = null;
            }
        });
        f.btnPause.addActionListener((e) -> {
            if (f.audioStream != null) {
                AudioPlayer.player.stop(f.audioStream);
               
            }
        });
    }

مطابق کد بالا نام شی ایجاد شده f هست که با استفاده از آن مقداردهی و فراخوانی انجام شده است. آدرس فایل صوتی در این مثال در درایو D  و با اسم 1.wav مشخص می شود.

با استفاده از کلاس AudioStream که ورودی سازنده ی آن یک InputStream است، فایل صوتی مورد نظر را از آدرس مشخصی در آن قرار می دهیم و با استفاده از کلاس AudioPlayer.player عمل start و stop فایل صوتی انجام می شود.

لازم به ذکر است که متدهای start و stop در کلاس AudioPlayer قرار دارند و ورودی آن ها از شی کلاس AudioStream است.

هر یک از سه دکمه ی قرارداده شده دارای یک addActionListener است که عمل مربوطه را انجام می دهند.

دو عمل stop و pause کاملا مشابه هستند و فقط در پایان عملیات pause فیلد audioStream مقدار null نمی گیرد. در نتیجه بخش else در play اجرا می شود و فایل صوتی از ادامه خوانده می شود.

package wavplayer;

import java.awt.Button;
import java.awt.Color;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import sun.audio.AudioPlayer;
import sun.audio.AudioStream;


public class WavPlayer {

    FileInputStream myMusic;
    String filepath = null;
    AudioStream audioStream = null;
    Button btnPlay;
    Button btnPause;
    Button btnStop;

    public static void main(String[] args) {
        WavPlayer f = new WavPlayer();
        f.Frame_main();
        try {
            f.myMusic = new FileInputStream(new File("D:\\1.wav"));
            f.audioStream = new AudioStream(f.myMusic);
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
        }
        f.btnPlay.addActionListener((e) -> {
            if (f.audioStream == null) {
                try {
                    f.myMusic = new FileInputStream(new File("D:\\1.wav"));
                    f.audioStream = new AudioStream(f.myMusic);
                    AudioPlayer.player.start(f.audioStream);
                } catch (Exception ex) {
                    System.err.println(ex.getMessage());
                }
            } else {
                AudioPlayer.player.start(f.audioStream);
            }
        });
        f.btnStop.addActionListener((e) -> {
            if (f.audioStream != null) {
                AudioPlayer.player.stop(f.audioStream);
                f.audioStream = null;
            }
        });
        f.btnPause.addActionListener((e) -> {
            if (f.audioStream != null) {
                AudioPlayer.player.stop(f.audioStream);
               
            }
        });
    }

    public  void Frame_main() {
        JFrame frame = new JFrame("wav player");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setLayout(null);
        frame.setResizable(false);
        frame.setSize(200, 200);
        frame.setVisible(true);
        btnPlay = new Button("play");
        btnStop = new Button("stop");
        btnPause = new Button("Pause");
        btnPlay.setBounds(70, 10, 60, 30);
        btnPause.setBounds(70, 50, 60, 30);
        btnStop.setBounds(70, 90, 60, 30);
        btnPlay.setBackground(Color.PINK);
        btnStop.setBackground(Color.cyan);
        btnPause.setBackground(Color.ORANGE);
        frame.add(btnPlay);
        frame.add(btnStop);
        frame.add(btnPause);
    }

}

بخش دوم MP3

در بخش دوم آموزش به بررسی مثالی در مورد پخش فایل MP3 در جاوا می پردازیم. برای درک کدهای این بخش علاوه بر آشنایی با OOP (برنامه نویسی شی گرا) و File باید با مبحث Thread را یاد گرفته باشید.

برای پخش فایل های mp3 در جاوا چندین کتابخانه وجود دارد که یکی از بهترین و البته ساده ترین آن ها کتابخانه ی jlayer-1.0.1 است که باید به پروژه اضافه و import شود. در پایان، فایل پروژه ی هر دو مثال و کتابخانه های لازم قرار داده می شود.

در NetBeans یک پروژه ی جدید ایجاد کنید.

در این مثال کدهای لازم را در کلاسی جداگانه نوشته تا با مثال قبل تفاوتی داشته باشد. سپس با ساختن شی از کلاس جدید (مثلا MediaClass) و استفاده از آن در متد main برنامه را کامل می کنیم.

فیلدهای زیر را در MediaClass تعریف کنید (نوع modifier اهمیت ندارد).

 private FileInputStream fis;
 private BufferedInputStream bis;
 private Player player;
 private long pauseloc;
 private long total;
 private Button btnStop;
 private Button btnPlay;
 private Button btnPause;
 private String filepath=null;

FileInputStream به عنوان شی ورودی برای سازنده ی کلاس BufferedInputStream است.

کلاس Player در واقع کلاس اصلی مربوط به بافر کردن فایل صوتی بوده که به عنوان ورودی سازنده، در شی کلاس BufferedInputStream مورد استفاده قرار می گیرد.

pauseloc موقعیت فعلی فایل (تا جای که خوانده شده) را در زمان pause کردن و total هم مقدار کل فایل را در خود نگه می دارد.

مانند مثال قبل به یک محیط ساده ی گرافیکی برای کنترل بیشتر روی دکمه ها نیاز داریم که میتوانیم متد قبلی را بدون تغییر استفاده کنیم.

 public void Frame_main() {
        JFrame frame = new JFrame("wav player");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setLayout(null);
        frame.setResizable(false);
        frame.setSize(200, 200);
        frame.setVisible(true);
        btnPlay = new Button("play");
        btnStop = new Button("stop");
        btnPause = new Button("Pause");
        btnPlay.setBounds(70, 10, 60, 30);
        btnPause.setBounds(70, 50, 60, 30);
        btnStop.setBounds(70, 90, 60, 30);
        btnPlay.setBackground(Color.PINK);
        btnStop.setBackground(Color.cyan);
        btnPause.setBackground(Color.ORANGE);
        frame.add(btnPlay);
        frame.add(btnStop);
        frame.add(btnPause);
    }

کد جاری سه متد اصلی دارد که به توضیح هر کدام می پردازیم:

  public void stop() {
        if (player != null) {
            player.close();
            fis=null;
        }
    }

ابتدا بررسی می کند که آیا فایلی play شده است یا خیر در صورتی که فایلی در حال اجرا باشد با استفاده از متد close() قطع شده و fis نیز برابر nall قرار داده می شود تا در صورت play شدن، فایلی جدید بارگذاری شود. ( برای تخلیه ی بافر)

 public void pause(){
        if(player !=null){
            try {
                pauseloc = fis.available();
            } catch (IOException ex) {  
            }
            player.close();
        }
    }

در این متد هم موجود بودن فایل بررسی می شود و در صورت وجود، قبل از اجرای خط player.close() مقدار فایل تا جایی که خوانده شده در فیلد pauseloc قرار می گیرد تا در جای مناسب استفاده شود.

public void play(String path) {
        if(fis==null){
       try { 
            fis = new FileInputStream(new File(path));
            bis = new BufferedInputStream(fis);
            player = new Player(bis);
            total = fis.available();
        } catch (FileNotFoundException | JavaLayerException ex) {
        } catch (IOException ex) {
        }
        }else {
            try {
                fis = new FileInputStream(new File(path));
                fis.skip(total-pauseloc);
            } catch (IOException ex) {  
            }
            bis = new BufferedInputStream(fis);
            try {
                player = new Player(bis);
            } catch (Exception  ex) {
            }
        }
            new Thread(){
                @Override
                public void run() {
                    try {
                        if(bis !=null){
                        player.play(); 
                        }
                    } catch (JavaLayerException ex) {
                        System.err.println(ex.getMessage());
                    }
                } 
            }.start();
    }

در ابتدای اجرا این کد، شرط null بودن fis بررسی می شود که مشخص می کند قبل از آن یا متد stop اجرا شده یا اولین بار است که برنامه start می شود. دلیل کد fis=null در متد stop به همین خاطر است.

در صورت اجرا شدن if فیلدها مقدار دهی شده و متغییر مهم total مقدار کل فایل را در خود ذخیره می کند. اما اجرا نشدن if به این معنی است که فایل قبلا در جریان بوده و متد pause اجرا شده. پس بخش else متد play اجرا می شود.

با مقدار دهی دوباره ی fis با همان فایل قبلی و اجرای خط کد زیر:

fis.skip(total-pauseloc)

در واقع مقدار کل فایل از مقدار گرفته شده در مرحله ی pause کم می شود و با play دوباره مقدار خوانده شده skip می شود و فایل صوتی از ادامه مقداری که باقی مانده، قابل بخش است که در نهایت با استفاده Thread و متد run  اجرا می شود.

مرحله ی آدرس دهی برای اجرای فایل صوتی، به عنوان پارامتر ورودی سازنده ی کلاس و addActionListener مربوط به Button ها نیز در همین بخش انجام گردیده است.

تذکر مهم: در صورت عدم استفاده از Thread فایل صوتی بدون مشکل اجرا شده ولی برنامه در همان خط گیر کرده و stop و pause و حتی بستن بنجره امکان پذیر نیست.

import java.awt.Button;
import java.awt.Color;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.swing.JFrame;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;
public class MediaClass {
    private FileInputStream fis;
    private BufferedInputStream bis;
    private Player player;
    private long pauseloc;
    private long total;
    private String Fileloc;
    private Button btnStop;
    private Button btnPlay;
    private Button btnPause;
    private String filepath=null;
     MediaClass(String filepath) {
        this.filepath=filepath;
        Frame_main();
        btnPlay.addActionListener((e)->{
            play(filepath);
        });
        btnStop.addActionListener((e)->{
            stop();
        });
       btnPause.addActionListener((e)->{
            pause();
        });
    }
    public void play(String path) {
        if(fis==null){
       try { 
            fis = new FileInputStream(new File(path));
            bis = new BufferedInputStream(fis);
            player = new Player(bis);
            total = fis.available();
        } catch (FileNotFoundException | JavaLayerException ex) {
        } catch (IOException ex) {
        }
        }else {
            try {
                fis = new FileInputStream(new File(path));
                fis.skip(total-pauseloc);
            } catch (IOException ex) {
               
            }
            bis = new BufferedInputStream(fis);
            try {
                player = new Player(bis);
            } catch (Exception  ex) {
            }
        }
            new Thread(){
                @Override
                public void run() {
                    try {
                        if(bis !=null){
                        player.play(); 
                        }
                    } catch (JavaLayerException ex) {
                        System.err.println(ex.getMessage());
                    }
                } 
            }.start();
    }
    public void stop() {
        if (player != null) {
            player.close();
            fis=null;
        }
    }
    public void pause(){
        if(player !=null){
            try {
                pauseloc = fis.available();
            } catch (IOException ex) {  
            }
            player.close();
        }
    }
    public void Frame_main() {
        JFrame frame = new JFrame("wav player");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setLayout(null);
        frame.setResizable(false);
        frame.setSize(200, 200);
        frame.setVisible(true);
        btnPlay = new Button("play");
        btnStop = new Button("stop");
        btnPause = new Button("Pause");
        btnPlay.setBounds(70, 10, 60, 30);
        btnPause.setBounds(70, 50, 60, 30);
        btnStop.setBounds(70, 90, 60, 30);
        btnPlay.setBackground(Color.PINK);
        btnStop.setBackground(Color.cyan);
        btnPause.setBackground(Color.ORANGE);
        frame.add(btnPlay);
        frame.add(btnStop);
        frame.add(btnPause);
    }

}
public class Mp3 {
    public static void main(String[] args) {
       MediaClass mc = new MediaClass("D:\\2.mp3"); 
    }  
}

مراحل اجرای فایل mp3 نسبت به wav دارای پیچیدگی بیشتری است ولی در مقابل، حجم فایل wav حدود 10 برابر mp3 می باشد.

بنابراین استفاده از فایل wav فقط در مواردی جایز است که مدت زمان فایل صوتی زیر 5 ثانیه باشد. (مثلا برای اجرای صدای کلیک موس در برنامه و...)

توجه: در صورت استفاده از فایل پروژه حتما قبل از اجرا، آدرس فایل صوتی مورد نظر در سیستم خودتان را در قسمت مربوط به آدرس فایل وارد کنید.

نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.