본문 바로가기
etc./Project

Chat-GPT를 이용한 가상 피아노

by k-mozzi 2023. 3. 7.
반응형
Preface

 

최근 들어 chatgpt라는 인공지능 채팅 시스템이 화제가 되어 한 두번씩 사용해보던 중 이 기술을 사용해 간단한 프로그램을 만들어보고싶다는 생각이 들었다.

 

어떤 프로그램을 제작할지 고민하다가 개발을 처음 시작할 때부터 만들어보고 싶었던 가상 피아노 코드를 부탁해보기로 결정했다.

 

물론 처음부터 완벽한 코드가 출력되지는 않고 몇 번의 수정을 거쳐야 했지만, 단지 몇 분만에 간단한 가상 피아노 코드가 뚝딱 완성되었다.

 

처음 부탁한 코드는 키보드로 값을 입력받아 소리를 출력하는 코드였고, 두 번째로 부탁한 코드는 기존의 코드를 GUI 형식으로 화면에 출력하여 사용자가 건반을 누르면 소리가 출력되는 코드였다.

 

이후 두 번째 코드에 서스테인 기능과 계이름 출력 기능, 마우스와 키보드 두 가지 입력 방식 모두를 지원하는 기능을 추가하려고 시도해봤지만, 길이가 너무 길어져서 그런지 코드가 중간에 끊기거나 나의 입력을 제대로 이해하지 못하는 현상이 발생했다.

 

또, 이번에 알게 된 사실인데 chatgpt에게 한 시간 내에 특정한 횟수 이상의 질문을 하면 일정 시간 동안 락이 걸려 더 이상 질문을 하지 못하게 된다.

 

비록 처음 원했던 모든 기능을 완벽히 구현하진 못했지만, 내가 직접 작성했으면 꽤 많은 시간이 소요됐을 코드를 너무 쉽고 빠르게 생성해버리는 인공지능의 모습을 보자 솔직히 조금 무서웠다.

 

이대로라면 개발자들이 설 자리가 점점 사라지지 않을까 싶다.

 

데이터 엔지니어링 쪽으로 빠르게 방향을 틀어야 하나...

 

앞으로도 종종 gpt를 통해 간단한 프로그램을 만들어 볼 생각이다.


 

1. 키보드로 값을 입력받아 소리를 출력하는 코드

package PianoProject;

import javax.sound.midi.*;

public class PianoExample {
    // MIDI 장치 초기화
    Synthesizer synth;
    MidiChannel[] channels;
    MidiChannel channel;

    public PianoExample() throws MidiUnavailableException {
        synth = MidiSystem.getSynthesizer();
        synth.open();
        channels = synth.getChannels();
        channel = channels[0];
    }

    // 검은 건반을 누를 때 소리를 내는 함수
    void playBlackKey(int noteNumber) {
        channel.noteOn(noteNumber, 100);
        try { Thread.sleep(100); } catch (Exception e) { }
        channel.noteOff(noteNumber);
    }

    // 흰 건반을 누를 때 소리를 내는 함수
    void playWhiteKey(int noteNumber) {
        channel.noteOn(noteNumber, 100);
        try { Thread.sleep(200); } catch (Exception e) { }
        channel.noteOff(noteNumber);
    }

    public static void main(String[] args) throws Exception {
        PianoExample piano = new PianoExample();

        // 사용자의 입력을 받아 건반을 누르고 소리를 내는 코드
        java.util.Scanner scanner = new java.util.Scanner(System.in);
        while (true) {
            System.out.println("Enter key (a-g, 1-7):");
            String key = scanner.nextLine().toLowerCase();
            int noteNumber = -1;
            if (key.equals("x")) {
                break;
            }
            switch (key) {
                case "a": noteNumber = 58; break;
                case "w": noteNumber = 59; break;
                case "s": noteNumber = 60; break;
                case "e": noteNumber = 61; break;
                case "d": noteNumber = 62; break;
                case "f": noteNumber = 63; break;
                case "t": noteNumber = 64; break;
                case "g": noteNumber = 65; break;
                case "y": noteNumber = 66; break;
                case "h": noteNumber = 67; break;
                case "u": noteNumber = 68; break;
                case "j": noteNumber = 69; break;
                case "k": noteNumber = 70; break;
                case "o": noteNumber = 71; break;
                case "l": noteNumber = 72; break;
                default: break;
            }
            if (noteNumber != -1) {
                if (key.equals("s") || key.equals("d") || key.equals("g") || key.equals("h") || key.equals("j")) {
                    piano.playBlackKey(noteNumber);
                } else {
                    piano.playWhiteKey(noteNumber);
                }
            }
        }
    }
}

 

 

2. 1번 코드를 GUI 형식으로 화면에 출력하여 사용자가 건반을 누르면 소리가 출력되는 코드

package PianoProject;

import javax.sound.midi.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class PianoGUI extends JFrame implements ActionListener {
	Synthesizer synth;
	MidiChannel[] channels;
	MidiChannel channel;
	JButton[] whiteKeys = new JButton[7];
	JButton[] blackKeys = new JButton[5];
	int[] whiteNoteNumbers = { 60, 62, 64, 65, 67, 69, 71 };
	int[] blackNoteNumbers = { 61, 63, 66, 68, 70 };
	Dimension whiteKeySize = new Dimension(60, 200);
	Dimension blackKeySize = new Dimension(40, 130);
	Color whiteKeyColor = new Color(252, 252, 252);
	Color blackKeyColor = new Color(20, 20, 20);

	public PianoGUI() throws MidiUnavailableException {
		synth = MidiSystem.getSynthesizer();
		synth.open();
		channels = synth.getChannels();
		channel = channels[0];

		// 흰 건반 버튼 생성
		JPanel whitePanel = new JPanel(new GridLayout(1, 7));
		for (int i = 0; i < whiteKeys.length; i++) {
			whiteKeys[i] = new JButton();
			whiteKeys[i].setPreferredSize(whiteKeySize);
			whiteKeys[i].setBorder(BorderFactory.createLineBorder(Color.BLACK));
			whiteKeys[i].setBackground(whiteKeyColor);
			whiteKeys[i].addActionListener(this);
			whitePanel.add(whiteKeys[i]);
		}

		// 검은 건반 버튼 생성
		JPanel blackPanel = new JPanel(new GridLayout(1, 5));
		for (int i = 0; i < blackKeys.length; i++) {
			blackKeys[i] = new JButton();
			blackKeys[i].setPreferredSize(blackKeySize);
			blackKeys[i].setBorder(BorderFactory.createLineBorder(Color.BLACK));
			blackKeys[i].setBackground(blackKeyColor);
			blackKeys[i].addActionListener(this);
			blackPanel.add(blackKeys[i]);
		}

		// 건반 배치
		JPanel keyboardPanel = new JPanel(new BorderLayout());
		keyboardPanel.add(whitePanel, BorderLayout.CENTER);
		keyboardPanel.add(blackPanel, BorderLayout.NORTH);
		add(keyboardPanel);
		setTitle("Piano");
		setSize(760, 280);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}

	void playNote(int noteNumber) {
		channel.noteOn(noteNumber, 100);
		try {
			Thread.sleep(200);
		} catch (Exception e) {
		}
		channel.noteOff(noteNumber);
	}

	public void actionPerformed(ActionEvent e) {
		JButton button = (JButton) e.getSource();
		int noteNumber = -1;

		// 흰 건반 처리
		for (int i = 0; i < whiteKeys.length; i++) {
			if (button == whiteKeys[i]) {
				noteNumber = whiteNoteNumbers[i];
				break;
			}
		}

		// 검은 건반 처리
		for (int i = 0; i < blackKeys.length; i++) {
			if (button == blackKeys[i]) {
				noteNumber = blackNoteNumbers[i];
				break;
			}
		}

		// 소리 출력
		if (noteNumber != -1) {
			playNote(noteNumber);
		}
	}

	public static void main(String[] args) throws Exception {
		new PianoGUI();
	}
}

 

 

3. 2번 코드에 서스테인 기능과 계이름 출력 기능, 마우스와 키보드 두 가지 입력 방식 모두를 지원하는 기능을 추가한 코드를 다시 한 번 gpt에게 부탁해 볼 생각이다.

728x90
반응형

댓글