202 lines
6.9 KiB
Markdown
202 lines
6.9 KiB
Markdown
# **Java `javax.sound.midi` 쉽게 배우기**
|
|
|
|
## **1. `javax.sound.midi`란?**
|
|
`javax.sound.midi` 패키지는 **자바에서 MIDI(악기 디지털 인터페이스) 데이터를 다루는 기능**을 제공한다.
|
|
이를 이용하면 **MIDI 파일을 재생, 편집, 녹음, 생성**할 수 있다.
|
|
|
|
**주요 기능**
|
|
✔ **MIDI 파일 재생** (악기 소리 출력)
|
|
✔ **MIDI 이벤트 생성 및 수정** (노트 추가/삭제)
|
|
✔ **실시간 MIDI 입력/출력** (MIDI 키보드 연결 가능)
|
|
|
|
---
|
|
|
|
## **2. 주요 클래스 및 메서드 정리**
|
|
|
|
### **(1) `MidiSystem` 클래스 (MIDI 시스템 제어)**
|
|
| 메서드 | 설명 |
|
|
|--------|------------------------------|
|
|
| `getSequencer()` | MIDI 파일을 재생하는 `Sequencer` 객체 반환 |
|
|
| `getSynthesizer()` | 소프트웨어 신시사이저(`Synthesizer`) 반환 |
|
|
| `getReceiver()` | MIDI 데이터를 출력할 `Receiver` 반환 |
|
|
| `getTransmitter()` | MIDI 데이터를 입력받을 `Transmitter` 반환 |
|
|
|
|
---
|
|
|
|
### **(2) `Sequencer` 클래스 (MIDI 재생기)**
|
|
| 메서드 | 설명 |
|
|
|--------|------------------------------|
|
|
| `open()` | `Sequencer`를 초기화하고 사용 준비 |
|
|
| `setSequence(Sequence sequence)` | 재생할 MIDI 시퀀스 설정 |
|
|
| `start()` | MIDI 재생 시작 |
|
|
| `stop()` | MIDI 재생 중지 |
|
|
| `setLoopCount(int count)` | MIDI 반복 재생 설정 |
|
|
|
|
---
|
|
|
|
### **(3) `Synthesizer` 클래스 (신시사이저 - 소리 생성)**
|
|
| 메서드 | 설명 |
|
|
|--------|------------------------------|
|
|
| `open()` | 신시사이저를 활성화 |
|
|
| `getChannels()` | MIDI 채널(`MidiChannel[]`) 가져오기 |
|
|
| `getReceiver()` | 신시사이저에 MIDI 메시지를 보내는 `Receiver` 반환 |
|
|
|
|
---
|
|
|
|
### **(4) `MidiChannel` 클래스 (MIDI 음원 채널)**
|
|
| 메서드 | 설명 |
|
|
|--------|------------------------------|
|
|
| `noteOn(int note, int velocity)` | 특정 음을 연주 (노트 켜기) |
|
|
| `noteOff(int note)` | 특정 음을 멈춤 (노트 끄기) |
|
|
| `setInstrument(Instrument instrument)` | 채널의 악기 변경 |
|
|
|
|
---
|
|
|
|
### **(5) `Sequence` 클래스 (MIDI 데이터 관리)**
|
|
| 메서드 | 설명 |
|
|
|--------|------------------------------|
|
|
| `createTrack()` | 새로운 `Track`(MIDI 트랙) 생성 |
|
|
| `getTracks()` | 시퀀스에 포함된 `Track` 목록 가져오기 |
|
|
|
|
---
|
|
|
|
### **(6) `Track` 클래스 (MIDI 트랙)**
|
|
| 메서드 | 설명 |
|
|
|--------|------------------------------|
|
|
| `add(MidiEvent event)` | MIDI 이벤트 추가 |
|
|
| `remove(MidiEvent event)` | MIDI 이벤트 제거 |
|
|
|
|
---
|
|
|
|
### **(7) `MidiEvent` 클래스 (MIDI 이벤트)**
|
|
| 메서드 | 설명 |
|
|
|--------|------------------------------|
|
|
| `new MidiEvent(MidiMessage message, long tick)` | 특정 시간(tick)에 MIDI 메시지 추가 |
|
|
|
|
---
|
|
|
|
## **3. MIDI 파일 재생 예제**
|
|
### **✔ MIDI 파일을 재생하는 코드 (`Sequencer` 사용)**
|
|
```java
|
|
import javax.sound.midi.*;
|
|
import java.io.File;
|
|
|
|
public class MidiPlayer {
|
|
public static void main(String[] args) {
|
|
try {
|
|
// MIDI 파일 로드
|
|
File midiFile = new File("song.mid");
|
|
Sequence sequence = MidiSystem.getSequence(midiFile);
|
|
|
|
// Sequencer 생성 및 열기
|
|
Sequencer sequencer = MidiSystem.getSequencer();
|
|
sequencer.open();
|
|
sequencer.setSequence(sequence);
|
|
|
|
// 재생 시작
|
|
sequencer.start();
|
|
System.out.println("MIDI 재생 시작!");
|
|
|
|
// 재생이 끝날 때까지 대기
|
|
while (sequencer.isRunning()) {
|
|
Thread.sleep(1000);
|
|
}
|
|
|
|
// 종료 처리
|
|
sequencer.close();
|
|
System.out.println("MIDI 재생 완료!");
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
```
|
|
✅ **MIDI 파일을 불러와 재생하는 코드이다.**
|
|
✅ **`Sequencer`를 사용하여 MIDI를 관리하고 재생한다.**
|
|
|
|
---
|
|
|
|
## **4. 실시간으로 MIDI 연주하기**
|
|
### **✔ 신시사이저를 사용해 실시간으로 MIDI 노트 출력**
|
|
```java
|
|
import javax.sound.midi.*;
|
|
|
|
public class MidiSynthesizer {
|
|
public static void main(String[] args) {
|
|
try {
|
|
// 신시사이저 열기
|
|
Synthesizer synthesizer = MidiSystem.getSynthesizer();
|
|
synthesizer.open();
|
|
|
|
// MIDI 채널 가져오기
|
|
MidiChannel[] channels = synthesizer.getChannels();
|
|
MidiChannel channel = channels[0]; // 첫 번째 채널 사용
|
|
|
|
// 특정 노트 연주 (도(C4) - MIDI 번호 60)
|
|
int note = 60;
|
|
channel.noteOn(note, 80); // 음을 켬 (velocity: 80)
|
|
System.out.println("도(C4) 연주 중...");
|
|
|
|
Thread.sleep(1000); // 1초 동안 연주
|
|
|
|
channel.noteOff(note); // 음을 끔
|
|
System.out.println("연주 종료!");
|
|
|
|
// 신시사이저 닫기
|
|
synthesizer.close();
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
```
|
|
✅ **`Synthesizer`를 사용해 실시간으로 MIDI 소리를 출력한다.**
|
|
✅ **`noteOn()`으로 음을 켜고 `noteOff()`로 끈다.**
|
|
|
|
---
|
|
|
|
## **5. 새로운 MIDI 파일 생성하기**
|
|
### **✔ MIDI 노트를 추가하여 새로운 MIDI 파일 생성**
|
|
```java
|
|
import javax.sound.midi.*;
|
|
import java.io.File;
|
|
|
|
public class MidiCreator {
|
|
public static void main(String[] args) {
|
|
try {
|
|
// 새로운 시퀀스 생성
|
|
Sequence sequence = new Sequence(Sequence.PPQ, 24);
|
|
Track track = sequence.createTrack();
|
|
|
|
// 노트 ON (C4 = 60)
|
|
ShortMessage noteOn = new ShortMessage();
|
|
noteOn.setMessage(ShortMessage.NOTE_ON, 0, 60, 80);
|
|
track.add(new MidiEvent(noteOn, 1));
|
|
|
|
// 노트 OFF (C4 = 60)
|
|
ShortMessage noteOff = new ShortMessage();
|
|
noteOff.setMessage(ShortMessage.NOTE_OFF, 0, 60, 80);
|
|
track.add(new MidiEvent(noteOff, 24));
|
|
|
|
// MIDI 파일로 저장
|
|
File midiFile = new File("new_song.mid");
|
|
MidiSystem.write(sequence, 1, midiFile);
|
|
|
|
System.out.println("새로운 MIDI 파일이 생성되었습니다: " + midiFile.getAbsolutePath());
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
```
|
|
✅ **새로운 MIDI 파일을 만들고, C4(도) 음을 추가하여 저장한다.**
|
|
✅ **`MidiEvent`를 사용하여 MIDI 데이터를 구성한다.**
|
|
|
|
---
|
|
|
|
## **6. 정리**
|
|
✔ **`javax.sound.midi`는 자바에서 MIDI 데이터를 다루는 API이다!**
|
|
✔ **MIDI 파일을 재생(`Sequencer`), 실시간 연주(`Synthesizer`), 노트 추가(`Track`, `MidiEvent`) 가능**
|
|
✔ **기본적으로 자바에서 제공하는 소프트웨어 신시사이저를 이용하여 다양한 MIDI 작업 가능**
|
|
|
|
✅ **MIDI 파일 플레이어, 가상 피아노, 미디 편집기 등을 만들 수 있다!** |