今回からは、期末の課題の制作期間です。
残り2回+〆切(1月末を予定)の期間で、以下の課題に取り組んで下さい。
テーマを以下の3つの中から選んで提出する。
テーマA
・JavaAppletによるキャラクターアニメーション
eclipse で Javaアプレットを作成する。
デザインパターンの解説で使用した、キャラクターを表現するクラスを拡張する。
要件:
オブジェクト指向のスタイルでコードを作成する。
オブジェクトの種類、振る舞い、アプレット画面に配置するオブジェクト数を 増加 させること。
テーマB
・Scala による音響合成プログラム
↓の資料で、音響合成のコードを紹介するので、これを拡張したプログラムを作成する。
要件:
音色の追加、音程・長さの指定、シーケンサー などの機能をプログラムして、演奏できるようにする。
テーマC
・Scala によるストリーム処理を利用したプログラム
テキスト処理を題材とする。
例)
HTMLファイルを入力とし、不要なデータを削除、または必要なデータを抽出など。
期末課題用のプロジェクトの名前は 学籍番号Final としてください。
提出はプロジェクトフォルダをレポートフォルダにコピーして提出です。
import javax.sound.sampled._// オーディオ形式を指定val SAMPLE_RATE = 44100; // 44.1KHzval audio_format = new AudioFormat(SAMPLE_RATE, 8, 1, true, true)val line = AudioSystem.getSourceDataLine(audio_format)line.open()line.start()// パターン作成val a:Stream[Byte] = 100.toByte #:: -100.toByte #:: a// パターン伸長def repeat(xs:Stream[Byte], n:Int) = xs.flatMap( e => Array.fill(n)(e) )// 音源作成val n1 = repeat(a,100).take(44100).toArrayval n2 = repeat(a,50).take(44100/2).toArray// 再生コマンドdef play(xs:Array[Byte]) = line.write(xs, 0, xs.length)// 単音再生play(n1)// 連続再生List(n1, n2, n1, n2, n1).foreach(play)コードで音源データとなる数列を作成:
SoundTest.scala の作成例)
import javax.sound.sampled._object SoundTest extends App { val SAMPLE_RATE = 44100; // 44.1KHz val audio_format = new AudioFormat(SAMPLE_RATE, 8, 1, true, true) val line = AudioSystem.getSourceDataLine(audio_format) line.open() line.start() // パターン作成(ブザー音) val a: Stream[Byte] = 100.toByte #:: -100.toByte #:: a // 無音(休符パターン) val m: Stream[Byte] = 0.toByte #:: m // サイン波 val b:Stream[Byte] = Array.tabulate(128)(i => (127*Math.sin(2*Math.PI*i/128)).toByte ).toStream #::: b // 一オクターブ上のサイン波(周波数2倍) val b2:Stream[Byte] = Array.tabulate(128)(i => (127*Math.sin(2*Math.PI*i/128 *2)).toByte ).toStream #::: b2 // パターン伸長 def repeat(xs: Stream[Byte], n: Int) = xs.flatMap(e => Array.fill(n)(e)) // 再生コマンド def play(xs: Array[Byte]) = line.write(xs, 0, xs.length) val m1 = m.take(44100).toArray val C4 = repeat(a, 100).take(44100 / 4).toArray val D4 = repeat(a, 100 * 8 / 9).take(44100 / 4).toArray val E4 = repeat(a, 100 * 4 / 5).take(44100 / 4).toArray val F4 = repeat(a, 100 * 3 / 4).take(44100 / 4).toArray val G4 = repeat(a, 100 * 2 / 3).take(44100 / 4).toArray val c4 = b.take(44100 / 4).toArray val cc4 = b2.take(44100 / 4).toArray List(c4, cc4, c4, cc4).foreach(play) List(c4, C4,D4,E4,F4,G4,F4,E4,D4,C4).foreach(play) line.drain() // 終了まで待機}2015年度以前の旧資料
Scala の REPL コマンド http://www.ne.jp/asahi/hishidama/home/tech/scala/scala.html
ファイル読み込みコマンド
:load ファイル名scala のプログラムファイルを読み込む。
試しに、先回の内容から、Scalaのプログラムをコピーして、3112789Finel.txt ファイルを作成し、読み込んで実行してみる。
読み込むファイルは、scala のコマンドと同じフォルダに置いておくと、パスを指定せずに済むので入力が楽。
または、 H: ドライブ(ユーザホーム)に保存して、 H:\ファイル名 で読み込む。
例)
import javax.sound.sampled._import scala.util.Random// オーディオ形式を指定val SAMPLE_RATE = 44100; // 44.1KHzval audio_format = new AudioFormat(SAMPLE_RATE, 8, 1, true, true)val line = AudioSystem.getSourceDataLine(audio_format)line.open()line.start()// 基準となる音の高さval frequency = 440// 1秒間分のデータval b1 = new Array[Byte](SAMPLE_RATE)// バイト列に適当な矩形波を作成
for (i <- 0 to b1.size -1) { val r = i / (SAMPLE_RATE / frequency) if( r % 2 == 0) { b1(i) = 100 } else { b1(i) = -100 }}// 再生line.write(b1, 0, b1.length);line.drain() // 終了まで待機コードで音源データとなる数列を作成:
例)
// ホワイトノイズ// ランダムな数値 -100 ~ +100 を並べるval b2 = List.fill(SAMPLE_RATE)((Random.nextInt(200)-100).toByte).toArray// 基準より1オクターブ高い音val b3 = new Array[Byte](SAMPLE_RATE)for (i <- 0 to b3.size -1) { val r = i / (SAMPLE_RATE / frequency/2) if( r % 2 == 0) { b3(i) = 100 } else { b3(i) = -100 }}// 基準を ド として ソ の高さの音val b4 = new Array[Byte](SAMPLE_RATE)for (i <- 0 to b4.size -1) { val r = i / (SAMPLE_RATE / frequency/3*2) if( r % 2 == 0) { b4(i) = 100 } else { b4(i) = -100 }}// 基準を ド として ミ の高さの音
val b5 = new Array[Byte](SAMPLE_RATE)for (i <- 0 to b5.size -1) { val r = i / (SAMPLE_RATE / frequency/5*4) if( r % 2 == 0) { b5(i) = 100 } else { b5(i) = -100 }}// ドミソ の和音を合成val b154 = new Array[Byte](SAMPLE_RATE)for (i <- 0 to b154.size -1) {b154(i) = (( b1(i) + b5(i) + b4(i) )/3).toByte
}// 1/4秒再生
line.write(b1, 0, b1.size/ 4)// 1秒再生
line.write(b2, 0, b2.size)line.write(b3, 0, b3.size / 4)line.write(b5, 0, b5.size / 4)line.write(b4, 0, b4.size / 4)line.write(b154, 0, b154.size )// 1秒分の無音データを 全て 0 で用意する。
val b6:Array[Byte] = Array.fill(SAMPLE_RATE)(0)// 三角波 -128 -127 ... -2 -1 0 1 2 3 ... +126 +127 のループ val b7:Array[Byte] = Array.tabulate(SAMPLE_RATE)(i => (i % 256 -128).toByte)// 三角波 -128 -126 ... -2 0 2 4 ... +124 +126 のループ。1オクターブ上の音 val b8:Array[Byte] = Array.tabulate(SAMPLE_RATE)(i => (i*2 % 256 -128).toByte)// 基準音の2倍の高さのサイン波val b9:Array[Byte] = Array.tabulate(SAMPLE_RATE)(i => (128*Math.sin(2*Math.PI *i/(SAMPLE_RATE/frequency/2) )).toByte)line.write(b6, 0, b6.size )line.write(b7, 0, b7.size )line.write(b8, 0, b8.size )line.write(b9, 0, b9.size )