Scalaでサウンド

Scalaから Java の Sound API を利用して MIDI で演奏や、サウンドの再生ができる。

例)MIDIシーケンサーを利用する

テンポ40BPMで、楽器番号0(ピアノ)で、中央のド(48+12=60)で、音の強さ64で、1拍(24tick)で、3回鳴らす。

import javax.sound.midi._

import javax.sound.midi.spi._

object Test extends App {

val tempo = 40

val channel = 0

val pitch = 48+12

val velocity = 64

val instrument = 0

// シーケンスとトラックの準備

val sequence = new Sequence(Sequence.PPQ, 24)

val track = sequence.createTrack()

// 演奏テンポ設定のMIDIメッセージ作成

val message0 = new MetaMessage()

val t = 60*1000*1000/tempo

message0.setMessage(0x51,Array(t>>16,t>>8&255,t&255) map {_.toByte},3)

track.add(new MidiEvent(message0,0))

// 楽器設定のMIDIメッセージ作成

val message1 = new ShortMessage()

message1.setMessage(ShortMessage.PROGRAM_CHANGE, channel, instrument, 0)

track.add(new MidiEvent(message1, 0))

// 音を出すMIDIメッセージ

val message2 = new ShortMessage()

message2.setMessage(ShortMessage.NOTE_ON, channel, pitch, velocity)

// 音を止めるMIDIメッセージ

val message3 = new ShortMessage()

message3.setMessage(ShortMessage.NOTE_OFF, channel, pitch, velocity)

// tick 0で音を出して、tick 24で音を止めるメッセージを シーケンスのトラックに書き込む

track.add(new MidiEvent(message2, 0))

track.add(new MidiEvent(message3, 24))

track.add(new MidiEvent(message2, 24))

track.add(new MidiEvent(message3, 48))

track.add(new MidiEvent(message2, 48))

track.add(new MidiEvent(message3, 72))

// シーケンサーを設定してMIDIシーケンスを再生

val sequencer = MidiSystem.getSequencer()

sequencer.open()

sequencer.setSequence(sequence)

sequencer.start()

}

例) ソフトシンセを利用する

import javax.sound.midi._

object Test2 extends App {

val synthesizer = MidiSystem.getSynthesizer()

synthesizer.open()

val instruments = synthesizer.getDefaultSoundbank().getInstruments()

// 楽器 0 をシンセサイザーに設定

synthesizer.loadInstrument(instruments(0))

val channel = synthesizer.getChannels()(0)

// ド レ ミ と 1秒(1000ms) 間隔で 演奏。

channel.noteOn(60 , 64) // 60の高さで音声出力

Thread.sleep(1000) // 1000ms プログラムを停止

channel.noteOff(128) // 音声停止

channel.noteOn(62 , 64)

Thread.sleep(1000)

channel.noteOff(128)

channel.noteOn(64 , 64)

Thread.sleep(1000)

channel.noteOff(128)

}