Halo, Habr! Saya mempersembahkan bagi Anda terjemahan artikel
“Java Sound, Getting Started, Part 1, Playback” .
Suara di JAWA, Bagian Satu, Awal. Memutar suara
Ini adalah awal dari serangkaian delapan pelajaran yang akan membiasakan Anda dengan Java Sound API.
Apa yang masuk akal dalam persepsi manusia? Ini adalah perasaan yang kita alami ketika perubahan tekanan udara ditransmisikan ke area sensorik kecil di dalam telinga kita.
Dan tujuan utama pembuatan API Suara adalah untuk memberi Anda sarana untuk menulis kode, yang akan membantu mentransfer gelombang tekanan ke telinga subjek yang tepat pada waktu yang tepat.
Jenis suara di Jawa:
- Java Sound API mendukung dua jenis utama audio (suara).
- Suara didigitalkan dan direkam langsung sebagai file
- Rekam sebagai file MIDI. Sangat jauh, tetapi mirip dengan notasi musik, di mana alat musik dimainkan dalam urutan yang diinginkan.
Jenis ini sangat berbeda dalam esensinya dan kami akan berkonsentrasi pada yang pertama, karena dalam kebanyakan kasus kita berurusan dengan suara yang harus didigitalkan untuk merekam dari sumber eksternal ke file atau sebaliknya untuk mereproduksi suara yang sebelumnya direkam dari file tersebut.
Pratinjau
Java Sound API didasarkan pada konsep
garis dan mixer.Selanjutnya:
Kami akan menjelaskan karakteristik fisik dan listrik dari representasi analog suara sebagaimana diterapkan pada
mixer audio .
Kami akan beralih ke skenario band rock awal, yang menggunakan enam mikrofon dan dua speaker stereo dalam kasus ini. Kami membutuhkan ini untuk memahami pengoperasian mixer audio.
Selanjutnya, kita melihat sejumlah tema Java Sound untuk pemrograman, seperti garis, mixer, format untuk data audio, dan banyak lagi.
Kami akan memahami hubungan yang ada antara objek SourceDataLine, Klip, Mixer, AudioFormat dan membuat program sederhana yang mereproduksi audio.
Di bawah ini kami berikan contoh program ini, yang dapat Anda gunakan untuk merekam dan kemudian memutar suara yang direkam.
Di masa mendatang, kami akan memberikan penjelasan lengkap tentang kode program yang digunakan untuk tujuan ini. Tetapi sama sekali tidak sepenuhnya dalam pelajaran ini.
Contoh dan Pertimbangan Kode
Karakteristik fisik dan listrik dari suara analogTujuan dari pelajaran kami adalah untuk memperkenalkan Anda pada dasar-dasar pemrograman Java menggunakan Java Sound API.
Java Sound API didasarkan pada konsep mixer audio, yang merupakan perangkat yang biasa digunakan ketika memutar suara hampir di mana saja: dari konser rock hingga mendengarkan CD di rumah. Tetapi sebelum memulai penjelasan rinci tentang pengoperasian mixer audio, akan berguna untuk membiasakan diri dengan karakteristik fisik dan listrik dari suara analog itu sendiri.
Lihatlah Gambar. 1
Vasya Pupyrkin mendorong sebuah pidato.
Gambar ini menunjukkan Vasya berpidato menggunakan sistem yang dikenal sebagai alamat beralamat lebar. Sistem seperti itu biasanya meliputi mikrofon, amplifier, dan speaker. Tujuan dari sistem ini adalah untuk memperkuat suara Vasya sehingga ia dapat didengar bahkan dalam kerumunan besar.
Goyangan di udaraSecara singkat, ketika Vasya berbicara, pita suaranya menyebabkan partikel udara bergetar di laringnya. Ini mengarah pada munculnya gelombang suara, yang, pada gilirannya, menyebabkan membran mikrofon bergetar dan kemudian berubah menjadi getaran listrik dengan amplitudo sangat kecil yang secara tepat mensimulasikan getaran suara dari sumber asli Vasya. Sebuah penguat, seperti namanya, memperkuat getaran listrik ini. Kemudian mereka sampai ke pengeras suara, yang melakukan transformasi kebalikan dari getaran listrik yang diamplifikasi menjadi gelombang suara yang sangat diperkuat, tetapi yang bagaimanapun persisnya mengulangi gelombang yang sama yang dihasilkan dalam pita suara Vasya Pupyrkin.
Mikrofon dinamisSekarang mari kita lihat Gambar. 2, yang menunjukkan diagram skematik dari mikrofon yang disebut dinamis.
Fig. 2 Rangkaian mikrofon dinamisGetaran suara mempengaruhi membranTekanan getaran suara bekerja pada membran fleksibel di dalam mikrofon. Ini menyebabkan membran bergetar, sementara getaran membran mengulangi getaran gelombang suara.
Koil bergerakSebuah gulungan kawat tipis melekat pada membran mikrofon. Sebagai membran berosilasi, koil juga membuat gerakan bolak-balik di medan magnet inti yang terbuat dari magnet permanen yang kuat. Dan seperti Faraday juga didirikan, arus listrik muncul di koil.
Sinyal listrik mengikuti bentuk gelombang suara.Dengan demikian, dari arus yang sangat lemah yang diinduksi dalam koil, sinyal listrik bolak-balik diperoleh, mengulangi bentuk gelombang suara yang bekerja pada membran mikrofon. Selanjutnya, sinyal ini dalam bentuk tegangan bolak-balik dimasukkan ke input penguat dari Gambar. 1.
LoudspeakerBahkan, prinsip pengoperasian speaker mengulangi perangkat mikrofon dinamis, hanya dihidupkan ke arah yang berlawanan.
(Secara alami, dalam hal ini, kabel belitan jauh lebih tebal, dan membran jauh lebih besar untuk memastikan operasi dengan sinyal yang diperkuat)

Osilasi membran pengeras suara memengaruhi partikel udara dan menciptakan gelombang suara yang kuat. Bentuk gelombang ini persis mengulangi bentuk gelombang suara dengan intensitas yang jauh lebih rendah yang diciptakan oleh pita suara Vasya. Tetapi intensitas gelombang baru sekarang cukup untuk memastikan bahwa getaran suara dari Vasya mencapai telinga orang yang berdiri bahkan di barisan belakang kerumunan besar.
Konser rockPada saat ini, Anda mungkin bertanya-tanya, apa hubungannya semua ini dengan Java Sound API? Tapi tunggu sebentar, kami memimpin jalan menuju dasar-dasar mixer audio.
Sirkuit yang dijelaskan di atas cukup sederhana. Terdiri dari Vasya Pupyrkin, satu mikrofon, penguat dan pembicara. Sekarang perhatikan sirkuit dengan Gambar. 4, yang menyajikan panggung yang disiapkan untuk konser rock dari grup musik awal.
Enam mikrofon dan dua speakerDalam Fig. 4 enam mikrofon terletak di atas panggung. Dua pengeras suara (speaker) terletak di sisi panggung. Ketika konser dimulai, para pemain menyanyikan atau memainkan musik di masing-masing dari enam mikrofon. Dengan demikian, kita akan memiliki enam sinyal listrik, yang harus diperkuat secara individual dan kemudian diumpankan ke kedua speaker. Selain itu, pemain dapat menggunakan berbagai efek khusus suara, misalnya, reverb, yang juga perlu dikonversi menjadi sinyal listrik sebelum menerapkannya ke speaker.
Dua speaker di sisi panggung dirancang untuk menciptakan efek suara stereo. Artinya, sinyal listrik yang berasal dari mikrofon yang terletak di atas panggung ke kanan harus jatuh ke speaker yang terletak di sebelah kanan. Demikian pula, sinyal dari mikrofon ke kiri harus diumpankan ke speaker yang terletak di sebelah kiri tempat kejadian. Tetapi sinyal listrik dari mikrofon lain yang terletak lebih dekat ke tengah panggung harus sudah dikirim ke kedua speaker dalam proporsi yang sesuai. Dan dua mikrofon tepat di tengah harus mentransmisikan sinyalnya ke kedua speaker secara sama.
Mixer audioTugas yang dibahas di atas hanya dilakukan oleh perangkat elektronik yang disebut mixer audio.
Garis audio (saluran)Meskipun penulis bukan ahli dalam mixer audio, dalam pengertiannya yang sederhana, mixer audio khas memiliki kemampuan untuk menerima input sejumlah independen dari masing-masing sinyal listrik lainnya, yang masing-masing mewakili sinyal audio asli atau saluran
(saluran).(Konsep saluran audio akan menjadi sangat penting ketika kita mulai memahami Java Sound API secara rinci.
Pemrosesan independen setiap saluran audioBagaimanapun, mixer audio standar memiliki kemampuan untuk memperkuat setiap saluran audio secara independen dari saluran lainnya. Juga, mixer biasanya memiliki kemampuan untuk memaksakan efek suara khusus, seperti, misalnya, reverb ke salah satu jalur audio. Pada akhirnya, mixer, seperti namanya, dapat mencampur semua sinyal listrik individu di saluran output seperti yang akan diatur, sehingga untuk mengontrol kontribusi setiap saluran audio ke saluran output. (Kontrol ini biasanya disebut panci atau panci - distribusi dalam ruang).
Kembali ke suara stereoJadi, dalam diagram dengan Gambar. 4, insinyur suara dari mixer audio memiliki kemampuan untuk menggabungkan sinyal dari enam mikrofon untuk mendapatkan dua sinyal output, yang masing-masing ditransmisikan ke pengeras suara.
Agar operasi berhasil, sinyal dari masing-masing mikrofon harus disediakan dalam proporsi yang sesuai, tergantung pada lokasi fisik mikrofon di atas panggung. (Dengan mengubah panning, sound engineer yang berkualitas dapat mengubah kontribusi setiap mikrofon jika perlu, jika, misalnya, vokalis utama bergerak di sekitar panggung selama konser).
Saatnya kembali ke dunia pemrogramanMari kita kembali dari dunia fisik ke dunia pemrograman. Menurut Sun:
“Java Sound tidak melibatkan konfigurasi perangkat keras khusus; Ini dirancang untuk memungkinkan berbagai komponen audio dipasang pada sistem dan tersedia untuk pengguna melalui API. Java Sound mendukung fungsi input dan output standar dari kartu suara (misalnya, untuk merekam dan memutar file audio), serta kemampuan untuk mencampur beberapa stream audio ”Mixer dan saluranSeperti yang telah disebutkan, Java Sound API dibangun di atas konsep mixer dan saluran. Jika Anda berpindah dari dunia fisik ke dunia pemrograman, maka Sun menulis yang berikut tentang mixer:
“Mixer adalah perangkat audio dengan satu atau lebih saluran. Tetapi mixer yang benar-benar mencampur sinyal audio harus memiliki beberapa saluran input sumber sumber dan setidaknya satu saluran target keluaran. "Baris input dapat menjadi instance dari kelas dengan objek SourceDataLine, dan baris output dapat objek TargetDataLine. Mixer juga dapat menerima suara yang direkam sebelumnya dan loop sebagai input, mendefinisikan saluran sumber inputnya sebagai instance dari objek kelas yang mengimplementasikan antarmuka Klip.
Antarmuka saluran saluran.
Sun melaporkan hal-hal berikut dari antarmuka Line: “
Line adalah elemen dari pipa audio digital seperti input atau output port audio, mixer, atau jalur audio ke atau dari mixer. Data audio yang melewati saluran dapat berupa mono atau multi-saluran (misalnya, stereo). ... Saluran dapat memiliki Kontrol, seperti gain, pan, dan reverb. "Menyatukan persyaratanJadi, kutipan di atas dari Sun menunjukkan persyaratan berikut
Sourcedataline
Targetgetataline
Pelabuhan
Klip
Kontrol
Fig. Gambar 5 menunjukkan contoh penggunaan istilah-istilah ini untuk membangun program keluaran audio sederhana.
Skrip programDari sudut pandang perangkat lunak 5 memperlihatkan objek Mixer yang diperoleh dengan satu objek Klip dan dua objek SourceDataLine.
Apa itu KlipKlip adalah objek pada input mixer, yang isinya tidak berubah seiring waktu. Dengan kata lain, Anda memuat data audio ke objek Klip sebelum Anda memainkannya. Konten audio objek Klip mungkin diputar satu kali atau lebih. Anda dapat memutar kembali Klip dan kemudian konten akan diputar berulang kali.
Input streamObjek SourceDataLine, di sisi lain, adalah objek aliran pada input mixer. Objek jenis ini dapat menerima aliran data audio dan mengirimkannya ke mixer secara real time. Data audio yang diperlukan dapat diperoleh dari berbagai sumber, seperti file audio, koneksi jaringan atau buffer memori.
Berbagai jenis saluranDengan demikian, objek Klip dan SourceDataLine dapat dianggap sebagai saluran input untuk objek Mixer. Masing-masing saluran input ini dapat memiliki: pan, gain, dan reverb.
Putar konten audioDalam sistem sederhana seperti itu, Mixer membaca data dari jalur input, menggunakan kontrol untuk mencampur sinyal input, dan memberikan output ke satu atau lebih saluran output, seperti speaker, output line, jack headphone, dan sebagainya.
Listing 11 menunjukkan program sederhana yang menangkap data audio dari port mikrofon, menyimpan data ini dalam memori, dan kemudian memainkannya melalui port speaker.
Kami hanya akan membahas pengambilan dan pemutaran. Sebagian besar program di atas adalah membuat jendela dan antarmuka grafis untuk pengguna sehingga memungkinkan untuk mengontrol perekaman dan pemutaran. Kami tidak akan membahas bagian ini sebagai melampaui tujuan. Tetapi kemudian kita akan mempertimbangkan penangkapan dan pemutaran data. Kami akan membahas kehilangan dalam pelajaran ini, dan menangkap di berikutnya. Sepanjang jalan, kita akan menggambarkan penggunaan saluran audio dengan Java Sound API.
Data yang diambil disimpan dalam objek ByteArrayOutputStream.
Potongan kode menyediakan untuk membaca data audio dari mikrofon dan menyimpannya sebagai objek ByteArrayOutputStream.
Metode yang disebut playAudio, yang dimulai pada Listing 1, memainkan data audio yang ditangkap dan disimpan dalam objek ByteArrayOutputStream.
private void playAudio() { try{ byte audioData[] = byteArrayOutputStream. toByteArray(); InputStream byteArrayInputStream = new ByteArrayInputStream( audioData);
Listing 1Kami mulai dengan kode standar.Cuplikan program pada Listing 1 sebenarnya belum terkait dengan Java Sound.
Tujuannya adalah untuk:
- Konversi data yang disimpan sebelumnya ke array tipe byte.
- Dapatkan aliran input untuk array data byte.
Kami membutuhkan ini untuk membuat data audio tersedia untuk pemutaran nanti.
Buka API SuaraBaris kode pada Listing 2 sudah terkait dengan Java Sound API.
AudioFormat audioFormat = getAudioFormat();
Listing 2Di sini kita secara singkat menyentuh topik tersebut, yang akan dibahas secara rinci dalam pelajaran selanjutnya.
Dua format independenPaling sering kita berhadapan dengan dua format independen untuk data audio.
Format file, (apa saja) yang berisi data audio (dalam program kami belum, karena data disimpan dalam memori)
Format data audio yang dikirimkan itu sendiri.
Apa itu format audio?Inilah yang Sun tulis tentang itu:
“Setiap saluran data memiliki format audio sendiri yang terkait dengan aliran datanya. Format (turunan dari AudioFormat) menentukan urutan byte dari aliran audio. Parameter format dapat berupa jumlah saluran, frekuensi sampling, bit kuantisasi, metode pengkodean, dll. Metode pengkodean yang biasa dapat berupa modulasi kode pulsa linier PCM dan variannya. "Urutan byteSumber data audio adalah urutan byte dari data biner. Ada berbagai opsi untuk bagaimana Anda dapat mengatur dan menafsirkan urutan ini. Kami tidak akan mulai membahas semua opsi ini secara terperinci, tetapi kami akan membahas sedikit format audio yang kami gunakan di sini dalam program kami.
Penyimpangan kecilDi sini kita meninggalkan metode playAudio untuk saat ini dan melihat metode getAudioFormat dari Listing 2.
Metode getAudioFormat lengkap ditunjukkan pada Listing 3. private AudioFormat getAudioFormat(){ float sampleRate = 8000.0F; int sampleSizeInBits = 16; int channels = 1; boolean signed = true; boolean bigEndian = false; return new AudioFormat( sampleRate, sampleSizeInBits, channels, signed, bigEndian); }
Listing 3Selain mendeklarasikan variabel yang diinisialisasi, kode dalam Listing 3 berisi satu ekspresi yang dapat dieksekusi.
Objek AudioFormatMetode getAudioFormat membuat dan mengembalikan instance objek kelas AudioFormat. Inilah yang Sun tulis tentang kelas ini:
“Kelas AudioFormat mendefinisikan urutan data spesifik dalam aliran audio. Beralih ke bidang objek AudioFormat, Anda bisa mendapatkan informasi tentang cara menafsirkan bit dengan benar dalam aliran data biner. "Kami menggunakan konstruktor paling sederhanaKelas AudioFormat memiliki dua jenis konstruktor (kami akan mengambil yang paling sepele). Parameter berikut diperlukan untuk konstruktor ini:
- Laju pengambilan sampel atau laju sampel per detik (Nilai yang tersedia: 8000, 11025, 16000, 22050, dan 44100 sampel per detik)
- Kedalaman bit data (tersedia 8 dan 16 bit per hitungan)
- Jumlah saluran (satu saluran untuk mono dan dua untuk stereo)
- Data yang ditandatangani atau tidak ditandatangani yang digunakan dalam aliran (misalnya, nilainya bervariasi dari 0 hingga 255 atau dari -127 hingga +127)
- Urutan byte Big-endian atau little-endian. (jika Anda mentransmisikan nilai byte stream 16-bit, penting untuk mengetahui byte mana yang lebih dulu - rendah atau tinggi, karena ada kedua opsi).
Seperti yang Anda lihat di Listing 3, dalam kasus kami, kami menggunakan parameter berikut untuk instance objek AudioFormat.
- 8000 sampel per detik
- 16 ukuran data
- data penting
- Perintah little-endian
Secara default, data dikodekan oleh PCM linier.
Konstruktor yang kami gunakan membuat turunan dari objek AudioFormat menggunakan modulasi kode pulsa linier dan parameter yang ditunjukkan di atas (Kami akan kembali ke PCM linier dan metode penyandian lainnya dalam pelajaran berikut)
Kembali ke metode playAudio lagiSekarang kita mengerti bagaimana format data audio bekerja dalam suara Java, mari kita kembali ke metode playAudio. Segera setelah kami ingin memutar data audio yang tersedia, kami membutuhkan objek kelas AudioInputStream. Kami mendapatkan instance dari itu di Listing 4.
audioInputStream = new AudioInputStream( byteArrayInputStream, audioFormat, audioData.length/audioFormat. getFrameSize());
Listing 4Parameter untuk konstruktor AudioInputStream- Konstruktor untuk kelas AudioInputStream memerlukan tiga parameter berikut:
- Aliran tempat instance objek AudioInputStream akan berbasis (seperti yang kita lihat untuk tujuan ini, kami menggunakan instance dari objek ByteArrayInputStream yang dibuat sebelumnya)
- Format data audio untuk aliran ini (untuk tujuan ini kami telah membuat turunan dari objek AudioFormat)
- Ukuran bingkai (frame) untuk data dalam aliran ini (lihat deskripsi di bawah)
- Dua parameter pertama jelas dari kode pada Listing 4. Namun, parameter ketiga tidak begitu jelas.
Dapatkan ukuran bingkaiSeperti yang dapat kita lihat dari Listing 4, nilai parameter ketiga dibuat menggunakan perhitungan. Ini hanyalah salah satu atribut dari format audio yang belum kami sebutkan sebelumnya, dan itu disebut bingkai.
Apa itu bingkai?Untuk PCM linier sederhana yang digunakan dalam program kami, frame berisi sekumpulan sampel untuk semua saluran pada waktu tertentu.
Dengan demikian, ukuran frame sama dengan ukuran hitungan dalam byte kali jumlah saluran.
Seperti yang mungkin sudah Anda duga, metode yang disebut getFrameSize mengembalikan ukuran bingkai dalam byte.
Perhitungan ukuran bingkaiDengan demikian, panjang data audio dalam suatu bingkai dapat dihitung dengan membagi jumlah total byte dalam urutan data audio dengan jumlah byte dalam satu frame. Perhitungan ini digunakan untuk parameter ketiga dalam Listing 4.
Mendapatkan Objek SourceDataLineBagian selanjutnya dari program yang akan kita bahas adalah sistem output audio sederhana. Seperti yang dapat kita lihat dari diagram pada Gambar. 5, untuk menyelesaikan masalah ini, kita memerlukan objek SourceDataLine.
Ada beberapa cara untuk mendapatkan instance dari objek SourceDataLine, yang semuanya sangat rumit. Kode dalam Listing 5 mengambil dan menyimpan referensi ke turunan objek SourceDataLine.
(Perhatikan bahwa kode ini tidak hanya membuat instance objek SourceDataLine. Ia mendapatkannya dengan cara yang agak bundar.)
DataLine.Info dataLineInfo = new DataLine.Info( SourceDataLine.class, audioFormat); sourceDataLine = (SourceDataLine) AudioSystem.getLine( dataLineInfo);
Listing 5Apa itu objek SourceDataLine?
Tentang ini, Sun menulis sebagai berikut:
“SourceDataLine adalah saluran data tempat data dapat ditulis. Ini berfungsi sebagai input untuk mixer. Aplikasi menulis urutan byte ke SourceDataLine, yang buffer data dan mengirimkannya ke mixer. Mixer dapat mengirimkan data yang diprosesnya ke tahap berikutnya, misalnya, ke port output.
Perhatikan bahwa konvensi penamaan untuk pemasangan ini mencerminkan hubungan antara saluran dan mixernya. "Metode GetLine untuk kelas AudioSystemSalah satu cara untuk mendapatkan instance dari objek SourceDataLine adalah dengan memanggil metode getLine statis dari kelas AudioSystem (Kami akan memiliki banyak untuk melaporkannya dalam pelajaran berikutnya).
Metode getLine memerlukan parameter input dari tipe Line.Info dan mengembalikan objek Line yang cocok dengan deskripsi di objek Line.Info yang sudah ditentukan.
Penyimpangan singkat lainnyaSun melaporkan informasi berikut tentang objek Line.Info:
“Saluran memiliki objek informasinya sendiri (turunan Line.Info), yang menunjukkan mixer mana (jika ada) mengirim data audio campuran sebagai output langsung ke saluran, dan mixer mana (jika ada) yang menerima data audio sebagai input langsung dari saluran. Varietas Garis dapat sesuai dengan subkelas Line.Info, yang memungkinkan Anda menentukan jenis parameter lain yang terkait dengan jenis saluran tertentu ”
Objek DataLine.InfoEkspresi pertama di Listing 5 membuat instance baru dari objek DataLine.Info, yang merupakan bentuk khusus (subkelas) dari objek Line.Info.
Ada beberapa konstruktor kelebihan beban untuk kelas DataLine.Info. Kami telah memilih yang paling mudah digunakan. Konstruktor ini memerlukan dua parameter.
Obyek KelasParameter pertama adalah Kelas, yang mewakili kelas yang kami definisikan sebagai SourceDataLine.class
Parameter kedua menentukan format data yang diinginkan untuk saluran. Kami menggunakan instance objek AudioFormat untuknya, yang telah ditentukan sebelumnya.
Di mana kita sudah?Sayangnya, kami masih belum memiliki objek SourceDataLine yang paling dibutuhkan. Sejauh ini, kami memiliki objek yang hanya menyediakan informasi tentang objek SourceDataLine yang kami butuhkan.
Mendapatkan Objek SourceDataLineEkspresi kedua di Listing 5 akhirnya membuat dan menyimpan instance dari SourceDataLine yang kita butuhkan. Ini terjadi dengan memanggil metode statis getLine dari kelas AudioSystem dan meneruskan dataLineInfo sebagai parameter. (Dalam pelajaran selanjutnya, kita akan melihat bagaimana cara mendapatkan objek Line, bekerja langsung dengan objek Mixer).
Metode getLine mengembalikan referensi ke objek tipe Line, yang merupakan induk dari SourceDataLine. Oleh karena itu, downcast diperlukan di sini sebelum nilai kembali disimpan sebagai SourceDataLine.
Mari kita siap menggunakan objek SourceDataLineSetelah kita mendapatkan instance dari objek SourceDataLine, kita perlu menyiapkannya untuk membuka dan menjalankan, seperti yang ditunjukkan pada Listing 6.
sourceDataLine.open(audioFormat); sourceDataLine.start();
Listing 6Metode pembukaanSeperti yang Anda lihat dari Listing 6, kami mengirim objek AudioFormat ke metode pembukaan untuk objek SourceDataLine.
Menurut Sun, ini adalah metode:
"Membuka saluran (saluran) dengan format yang ditentukan sebelumnya, memungkinkan dia untuk menerima sumber daya sistem apa pun yang dia butuhkan dan berada dalam kondisi kerja (berfungsi)"Negara penemuanAda sedikit lagi yang ditulis Sun tentangnya di utas ini.
“Membuka dan menutup saluran mempengaruhi distribusi sumber daya sistem. Pembukaan saluran yang berhasil memastikan bahwa semua sumber daya yang diperlukan disediakan untuk saluran tersebut.
Pembukaan mixer, yang memiliki port input dan output untuk data audio, termasuk, antara lain, menggunakan perangkat keras platform tempat pekerjaan dan inisialisasi komponen perangkat lunak yang diperlukan berlangsung.
Membuka saluran, yang merupakan rute untuk data audio ke atau dari mixer, termasuk menginisialisasi dan menerima sumber daya mixer tanpa batas. Dengan kata lain, mixer memiliki jumlah saluran yang terbatas, sehingga beberapa aplikasi dengan kebutuhan saluran mereka sendiri (dan bahkan kadang-kadang satu aplikasi) harus membagikan sumber daya mixer dengan benar) ”Panggil metode mulai di saluranMenurut Sun, memanggil metode mulai untuk saluran berarti yang berikut:
“Saluran diizinkan menggunakan jalur I / O. Jika upaya dilakukan untuk menggunakan jalur yang sudah beroperasi, metode tidak melakukan apa-apa. Tetapi setelah buffer data kosong, baris melanjutkan mulai I / O, mulai dari frame pertama yang tidak berhasil diproses setelah buffer dimuat penuh. "Dalam kasus kami, tentu saja, saluran tidak berhenti. Sejak kami meluncurkannya untuk pertama kalinya.
Sekarang kami memiliki hampir semua yang kami butuhkanPada titik ini, kami menerima semua sumber daya audio yang kami perlukan untuk memutar data audio yang sebelumnya kami rekam dan simpan dalam instance objek ByteArrayOutputStream. (Ingat bahwa objek ini hanya ada di RAM komputer).
Kami mulai mengalirKami akan membuat dan memulai aliran untuk memutar audio. Kode dalam Listing 7 membuat dan memulai utas ini.
(Jangan bingung panggilan ke metode mulai di utas ini dengan panggilan ke metode mulai di objek SourceDataLine dari Listing 6. Ini adalah operasi yang sama sekali berbeda)
Thread playThread = new Thread(new PlayThread()); playThread.start(); } catch (Exception e) { System.out.println(e); System.exit(0); }
Listing 7Kode bersahajaCuplikan program di Listing 7, meskipun sangat sederhana, menunjukkan contoh pemrograman multi-utas di Jawa. Jika Anda tidak memahaminya, maka Anda harus membiasakan diri dengan topik ini dalam topik khusus untuk mempelajari Java.
Setelah streaming dimulai, itu akan berfungsi sampai semua data audio yang direkam sebelumnya telah diputar sampai akhir.
Objek Utas BaruKode dalam Listing 7 membuat turunan objek Thread dari kelas PlayThread. Kelas ini didefinisikan sebagai kelas dalam di program kami. Uraiannya dimulai pada Listing 8.
class PlayThread extends Thread{ byte tempBuffer[] = new byte[10000];
Listing 8Metode jalankan di kelas ThreadKecuali untuk mendeklarasikan variabel tempBuffer (yang mengacu pada array byte), definisi lengkap dari kelas ini hanyalah definisi dari metode yang dijalankan. Seperti yang seharusnya sudah Anda ketahui, memanggil metode mulai pada objek Thread menyebabkan menjalankan metode objek ini untuk mengeksekusi
Metode run untuk utas ini dimulai pada Listing 9.
public void run(){ try{ int cnt;
Listing 9Bagian pertama dari fragmen program dalam menjalankan metodeMetode run berisi dua bagian penting, yang pertama ditunjukkan pada Listing 9.
Singkatnya, sebuah loop digunakan di sini untuk membaca data audio dari AudioInputStream dan meneruskannya ke SourceDataLine.
Data yang dikirim ke objek SourceDataLine secara otomatis ditransfer ke output audio default. Ini bisa berupa speaker komputer built-in atau output line. (Kami akan belajar menentukan perangkat suara yang diperlukan dalam pelajaran berikut). Variabel cnt dan buffer data tempBuffer digunakan untuk mengontrol aliran data antara operasi baca dan tulis.
Membaca data dari AudioInputStreamSiklus baca dari objek AudioInputStream membaca jumlah maksimum byte data yang ditentukan dari AudioInputStream dan menempatkan array byte mereka.
Nilai pengembalianSelanjutnya, metode ini mengembalikan jumlah total byte yang dibaca, atau -1, jika akhir dari urutan yang direkam tercapai. Jumlah byte yang dibaca disimpan dalam variabel cnt.
SourceDataLine menulis loopJika jumlah byte yang dibaca lebih besar dari nol, maka ada transisi ke siklus penulisan data ke SourceDataLine. Dalam loop ini, data audio memasuki mixer. Bytes dibaca dari array byte sesuai dengan indeks mereka dan ditulis ke buffer saluran.
Saat aliran input mengeringKetika loop baca mengembalikan -1, ini berarti bahwa semua data audio yang direkam sebelumnya telah berakhir dan kontrol lebih lanjut diteruskan ke fragmen program dalam Listing 10.
sourceDataLine.drain(); sourceDataLine.close(); }catch (Exception e) { System.out.println(e); System.exit(0); }
Listing 10Kunci dan tungguKode dalam Listing 10 memanggil metode drain pada objek SourceDataLine sehingga program dapat memblokir dan menunggu buffer internal kosong di SourceDataLine. Ketika buffer kosong, itu berarti seluruh bagian selanjutnya dikirim ke output suara komputer.
Menutup SourceDataLineKemudian program memanggil metode tutup untuk menutup saluran, sehingga menunjukkan bahwa semua sumber daya sistem yang digunakan oleh saluran sekarang bebas. Sun melaporkan penutupan saluran berikut:
“Menutup sinyal saluran bahwa semua sumber daya yang terlibat untuk saluran ini dapat dibebaskan. Untuk membebaskan sumber daya, aplikasi harus menutup saluran, apakah mereka sudah terlibat atau belum, serta ketika aplikasi berakhir. Diasumsikan bahwa mixer berbagi sumber daya sistem dan dapat ditutup dan dibuka berulang kali. Saluran lain mungkin atau mungkin tidak mendukung pembukaan kembali setelah ditutup. Secara umum, mekanisme untuk membuka garis bervariasi sesuai dengan subtipe yang berbeda. "Dan sekarang akhir dari ceritaJadi di sini kami memberikan penjelasan tentang bagaimana program kami menggunakan Java Sound API untuk memastikan pengiriman data audio dari memori internal komputer ke kartu suara.
Jalankan programnyaSekarang Anda dapat mengkompilasi dan menjalankan program dari Listing 11, yang menandai akhir dari pelajaran kami.
Tangkap dan putar data audioProgram ini menunjukkan kemampuan untuk merekam data dari mikrofon dan memutarnya melalui kartu suara komputer Anda. Petunjuk untuk menggunakannya sangat sederhana.
Jalankan programnya. GUI GUI sederhana, yang ditunjukkan pada Gambar 6, akan muncul di layar.

- Klik tombol Ambil dan rekam suara apa pun ke mikrofon.
- Klik tombol Stop untuk berhenti merekam.
- Klik tombol Playback untuk memutar rekaman melalui output suara komputer Anda.
Jika Anda tidak mendengar apa pun, coba tingkatkan sensitivitas mikrofon atau volume speaker Anda.
Program menyimpan catatan dalam memori komputer, jadi berhati-hatilah. Jika Anda mencoba menyimpan terlalu banyak data audio, Anda mungkin kehabisan RAM.
Kesimpulan- Kami menemukan bahwa Java Sound API didasarkan pada konsep saluran dan mixer.
- Kami mendapat informasi awal tentang karakteristik fisik dan listrik dari suara analog, untuk kemudian memahami perangkat mixer audio.
- Kami menggunakan skenario konser rock amatir menggunakan enam mikrofon dan dua speaker stereo untuk menggambarkan kemungkinan menggunakan mixer audio.
- Kami membahas sejumlah topik pemrograman Java Sound, termasuk mixer, saluran, format data, dan banyak lagi.
- Kami menjelaskan hubungan umum antara objek SourceDataLine, Klip, Mixer, AudioFormat, dan porta dalam program sederhana untuk menghasilkan data audio.
- Kami berkenalan dengan sebuah program yang memungkinkan kami untuk merekam dan kemudian memutar data audio.
- Kami menerima penjelasan rinci tentang kode yang digunakan untuk memutar data audio yang direkam sebelumnya di memori komputer.
Apa selanjutnyaDalam tutorial ini, kami menemukan bahwa Java Sound API didasarkan pada konsep mixer dan saluran. Namun, kode yang kami diskusikan tidak menyertakan mixer secara eksplisit. Kelas AudioSystem memberi kami metode statis yang memungkinkan untuk menulis program pemrosesan audio tanpa secara langsung mengakses mixer. Dengan kata lain, metode statis ini mengambil mixer dari kami.
Dalam pelajaran berikutnya, kami menyajikan kode pengambilan data yang dimodifikasi dibandingkan dengan yang disajikan dalam pelajaran ini. Versi baru secara eksplisit akan menggunakan mixer untuk menunjukkan kepada Anda bagaimana menggunakannya ketika Anda benar-benar membutuhkannya. import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; import javax.sound.sampled.*; public class AudioCapture01 extends JFrame{ boolean stopCapture = false; ByteArrayOutputStream byteArrayOutputStream; AudioFormat audioFormat; TargetDataLine targetDataLine; AudioInputStream audioInputStream; SourceDataLine sourceDataLine; public static void main( String args[]){ new AudioCapture01(); }
Listing 11