マイペースなプログラミング日記

DTMやプログラミングにお熱なd-kamiがマイペースに書くブログ

なんとなくkotlinで書き直してみる

まだよくわかってないけどkotlinしてみる

import javafx.stage.Stage
import javafx.application.Application

import javafx.scene.Scene
import javafx.scene.control.Button
import javafx.scene.layout.BorderPane

import javafx.event.ActionEvent
import javafx.event.EventHandler

import javafx.animation.KeyFrame
import javafx.animation.Timeline
import javafx.animation.Animation

import javafx.util.Duration

import javax.sound.midi.Receiver
import javax.sound.midi.MidiSystem
import javax.sound.midi.ShortMessage

import javax.sound.midi.InvalidMidiDataException

fun main(args: Array<String>){
    Application.launch(DrumTest::class.java, *args)
}

class DrumTest() : Application(){
    private val receiver: Receiver
    
    private val pattern = "B-S-BBS-"
    private var patternIndex = 0
    
    init{
        receiver = MidiSystem.getReceiver()
    }
    
    override fun start(stage: Stage){
        val button = createDrumButton("8ビート!")
        val pane = BorderPane()
        
        pane.setCenter(button)
        
        val scene = Scene(pane, 320.0, 120.0)
        
        stage.setScene(scene)
        stage.show()
    }
    
    private fun createDrumButton(text: String): Button{
        val button = Button(text)
        
        val timer = Timeline(KeyFrame(Duration.millis(250.0), object : EventHandler<ActionEvent>{
            override fun handle(event: ActionEvent?){
                try{
                    if(pattern[patternIndex] == 'B'){
                        noteBassDrum();
                    }else if(pattern[patternIndex] == 'S'){
                        noteSnareDrum();
                    }
                }catch(ex: InvalidMidiDataException){
                    ex.printStackTrace();
                }

                patternIndex = (patternIndex + 1) % 8;
            }
        }))
        
        button.setOnAction({ _ ->
            if(timer.getStatus() == Animation.Status.STOPPED){
                timer.setCycleCount(16);
                timer.play();
            }
        })
        
        return button
    }
    
    private fun noteBassDrum(){
        val message = ShortMessage()
        message.setMessage(ShortMessage.NOTE_ON, 9, 36, 100)
        receiver.send(message, -1)
    }
    
    private fun noteSnareDrum(){
        val message = ShortMessage()
        message.setMessage(ShortMessage.NOTE_ON, 9, 38, 100)
        receiver.send(message, -1)
    }
}

参考
qiita.com

なんとなくバスドラムとスネアドラムで8ビート

ボタンを押すたびによくあるドラムの8ビートパターンを鳴らすようにしてみました。今回はボタンを押すたびにタイマを毎回生成しない仕様。しかもちゃんとタイマの状態をチェックしているので途中でパターンがおかしくなることもないと思われる

import javafx.stage.Stage;
import javafx.application.Application;

import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.animation.Animation;

import javafx.util.Duration;

import javax.sound.midi.Receiver;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.ShortMessage;

import javax.sound.midi.InvalidMidiDataException;
 
public class DrumTest extends Application {
    private Receiver receiver;
    private Timeline timer;
    
    private String pattern = "B-S-BBS-";
    private int patternIndex = 0;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception {
        receiver = MidiSystem.getReceiver();

        Button button = createDrumButton("8ビート!");
        BorderPane pane = new BorderPane();
        pane.setCenter(button);
        Scene scene = new Scene(pane, 320, 120);
        stage.setScene(scene);
        stage.show();
    }
    
    private Button createDrumButton(String text){
        Button button = new Button(text);
        
        timer = new Timeline(new KeyFrame(Duration.millis(250), event -> {
            try{
                if(pattern.charAt(patternIndex) == 'B'){
                    noteBassDrum();
                }else if(pattern.charAt(patternIndex) == 'S'){
                    noteSnareDrum();
                }
            }catch(InvalidMidiDataException ex){
                ex.printStackTrace();
            }
            
            patternIndex = (patternIndex + 1) % 8;
        }));
        
        button.setOnAction( e -> {
            if(timer.getStatus() == Animation.Status.STOPPED){
                timer.setCycleCount(16);
                timer.play();
            }
        });

        return button;
    }
    
    private void noteBassDrum() throws InvalidMidiDataException{
        ShortMessage message = new ShortMessage();
        message.setMessage(ShortMessage.NOTE_ON, 9, 36, 100);
        receiver.send(message, -1);
    }
    
    private void noteSnareDrum() throws InvalidMidiDataException{
        ShortMessage message = new ShortMessage();
        message.setMessage(ShortMessage.NOTE_ON, 9, 38, 100);
        receiver.send(message, -1);
    }
}

なんとなく定期的にバスドラムを鳴らしてみる

JavaFXのタイマ使って8回バスドラムを鳴らしてみます。
参考↓
JavaFX 8でタイマー(処理の定期実行)を実装する -- ぺけみさお

下記プログラムの弱点は!ボタンを押すたびに新しいタイマが起動してバスドラムを鳴らすので、実行中のタイマが終わる前にボタンを押しまくるとカオスになることですね!

import javafx.stage.Stage;
import javafx.application.Application;

import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;

import javafx.util.Duration;

import javax.sound.midi.Receiver;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.ShortMessage;

import javax.sound.midi.InvalidMidiDataException;
 
public class DrumTest extends Application {
    private Receiver receiver;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception {
        receiver = MidiSystem.getReceiver();

        Button button = createDrumButton("ドラム!");
        BorderPane pane = new BorderPane();
        pane.setCenter(button);
        Scene scene = new Scene(pane, 320, 120);
        stage.setScene(scene);
        stage.show();
    }
    
    private Button createDrumButton(String text){
        Button button = new Button(text);
        
        button.setOnAction( e -> {
            Timeline timer = new Timeline(new KeyFrame(Duration.millis(250), event -> {
                try{
                    ShortMessage message = new ShortMessage();
                    message.setMessage(ShortMessage.NOTE_ON, 9, 36, 100);
                    receiver.send(message, -1);
                }catch(InvalidMidiDataException ex){
                    ex.printStackTrace();
                }
            }));

            timer.setCycleCount(8);
            timer.play();
        });

        return button;
    }
}

なんとなくMIDIでバスドラムを1発鳴らしてみる

GM(?)ならとりあえず10チャンネルで音を鳴らせばドラムになる模様。バスドラムの音は36らしい。35にもなんかあるけど
https://ja.wikipedia.org/wiki/General_MIDI

チャンネル10だがプログラム的には0から始まる番号なので9になる。間違えて10って書きそう…

import javax.sound.midi.Receiver;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.ShortMessage;

class Test {
    public static void main(String[] args) throws Exception {
        Receiver receiver = MidiSystem.getReceiver();
        ShortMessage message = new ShortMessage();

        message.setMessage(ShortMessage.NOTE_ON, 9, 36, 127);
        receiver.send(message, -1);

        System.out.println("Enter キーを押してプログラムを終了します>");
        System.in.read();
    }
}

なんとなくMIDIデバイス列挙

何かプログラム作らないと…という思いから何かを作り始めているようだ…

import javafx.stage.Stage;
import javafx.application.Application;

import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.BorderPane;

import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiDevice;


public class DeviceList extends Application{
    public static void main(String[] args) {
        launch(args);
    }
    
    @Override
    public void start(Stage stage){
        ComboBox<MidiDevice.Info> devices = new ComboBox<MidiDevice.Info>();
        devices.getItems().addAll(MidiSystem.getMidiDeviceInfo());
        
        BorderPane pane = new BorderPane();
        pane.setCenter(devices);
        
        Scene scene = new Scene(pane, 320, 120);
        stage.setScene(scene);
        stage.show();
    }
}

f:id:d-kami:20170903083540p:plain