diff --git a/.gitignore b/.gitignore index 3bfd309..3fec32c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ tmp/ -etc/ diff --git a/pom.xml b/pom.xml index 495a0b9..1cf0d17 100644 --- a/pom.xml +++ b/pom.xml @@ -8,43 +8,14 @@ vavi vavi-sound - 1.0.11 + 1.0.12 Vavi Sound API https://github.com/umjammer/vavi-sound https://github.com/umjammer/vavi-sound - 1.0.7 - - simplify service loader - fix dependencies - -1.0.6 - - depends on vavi-commons api change - fix event listener duplication - -1.0.5 - - fix midi spi - -1.0.4 - - ssrc spi (wip) - -1.0.3 - - make build pass - -1.0.2 - - maintenance version - -1.0.1 - - refactor properties related - + TODO adpcm spi @@ -52,6 +23,42 @@ TODO https://github.com/umjammer/vavi-sound/issues + + + mac + + + mac + + + + /dev/null + + + + unix + + + unix + + + + /dev/null + + + + windows + + + windows + + + + NUL + + + + @@ -82,10 +89,11 @@ TODO maven-surefire-plugin - 3.0.0-M4 + 3.0.0-M5 -Djava.util.logging.config.file=${project.build.testOutputDirectory}/logging.properties + -Dvavi.test.dev.null=${dev.null} false @@ -104,44 +112,75 @@ TODO + + + + org.junit + junit-bom + 5.8.1 + pom + import + + + + com.github.umjammer vavi-commons - 1.1.4 + 1.1.6 com.github.umjammer klab-commons-cli 1.3.0 + + + com.github.umjammer + vavi-commons + + com.github.umjammer vavi-util-codec-sandbox 1.0.1 + + + com.github.umjammer + vavi-commons + + vavi vavi-sound-nda 1.0.10 + + + com.github.umjammer + vavi-commons + + + com.github.umjammer + vavi-sound + + org.junit.jupiter junit-jupiter-api - 5.3.0 test org.junit.jupiter junit-jupiter-engine - 5.3.0 test org.junit.platform junit-platform-commons - 1.5.2 test diff --git a/src/main/java/vavi/sound/SoundUtil.java b/src/main/java/vavi/sound/SoundUtil.java new file mode 100644 index 0000000..77d1953 --- /dev/null +++ b/src/main/java/vavi/sound/SoundUtil.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 by Naohide Sano, All rights reserved. + * + * Programmed by Naohide Sano + */ + +package vavi.sound; + +import javax.sound.sampled.DataLine; +import javax.sound.sampled.FloatControl; + + +/** + * SoundUtil. + * + * @author Naohide Sano (umjammer) + * @version 0.00 2022/02/13 umjammer initial version
+ */ +public final class SoundUtil { + + private SoundUtil() {} + + /** + * @param gain number between 0 and 1 (loudest) + * @before {@link DataLine#open()} + */ + public static void volume(DataLine line, double gain) { + FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); + float dB = (float) (Math.log10(gain) * 20.0); + gainControl.setValue(dB); + } +} + +/* */ diff --git a/src/main/java/vavi/sound/adpcm/ccitt/package.html b/src/main/java/vavi/sound/adpcm/ccitt/readme.md similarity index 52% rename from src/main/java/vavi/sound/adpcm/ccitt/package.html rename to src/main/java/vavi/sound/adpcm/ccitt/readme.md index 8759733..1c8fa54 100644 --- a/src/main/java/vavi/sound/adpcm/ccitt/package.html +++ b/src/main/java/vavi/sound/adpcm/ccitt/readme.md @@ -1,50 +1,19 @@ - +# vavi.sound.adpcm.ccitt - - - - - - - -vavi.sound.adpcm.ccitt - - - - - -

CCITT 勧告の音声圧縮フォーマット関連のクラスを提供します。 -

-
    -
  • encoder.exe は little endian
  • -
+## Tech-know -

わかったこと

+ * encoder.exe は little endian + * PCM_SIGNED の場合はちゃんと 16Bit Signed な数値を渡してやる -
    -
  • PCM_SIGNED の場合はちゃんと 16Bit Signed な数値を渡してやる
  • -
  • -
+## TODO -

これから実装すること

+ * 3, 5bit -
    -
  • 3, 5bit
  • -
  • -
+## License -

一次ライセンス

-
+```
 /*
  * This source code is a product of Sun Microsystems, Inc. and is provided
  * for unrestricted use.  Users may copy or modify this source code without
@@ -70,8 +39,4 @@ 

一次ライセンス

* 2550 Garcia Avenue * Mountain View, California 94043 */ -
- - - - +``` diff --git a/src/main/java/vavi/sound/adpcm/dvi/package.html b/src/main/java/vavi/sound/adpcm/dvi/readme.md similarity index 56% rename from src/main/java/vavi/sound/adpcm/dvi/package.html rename to src/main/java/vavi/sound/adpcm/dvi/readme.md index a63a088..0900896 100644 --- a/src/main/java/vavi/sound/adpcm/dvi/package.html +++ b/src/main/java/vavi/sound/adpcm/dvi/readme.md @@ -1,47 +1,22 @@ - - +# vavi.sound.adpcm.dvi - - - - - - -vavi.sound.adpcm.dvi - - - - - -

Intel/DVI ADPCM フォーマット関連のクラスを提供します. -

+ +## Status 完成 -

わかったこと

+## Tech-know -
    -
  • audiocafe の Java 移植はバグってる?
  • -
+ * audiocafe の Java 移植はバグってる? -

これから実装すること

+## TODO -
    -
  • 一括読み込みを止める
  • -
  • encode
  • -
+ * ~~datetime="060124 一括読み込みを止める~~ + * ~~encode~~ -

一次ライセンス

-
+## License
+```
 /***********************************************************
 Copyright 1992 by Stichting Mathematisch Centrum, Amsterdam, The
 Netherlands.
@@ -65,7 +40,4 @@ 

一次ライセンス

OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ -
- - - +``` diff --git a/src/main/java/vavi/sound/adpcm/ms/package.html b/src/main/java/vavi/sound/adpcm/ms/package.html deleted file mode 100644 index e8b6e68..0000000 --- a/src/main/java/vavi/sound/adpcm/ms/package.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - -vavi.sound.adpcm.ms - - - - - -

-MS ADPCM フォーマット関連のクラスを提供します. -

- -sox と同じ結果になったので完成とみなす。 - -

分かったこと

- -
    -
  • ACM の M$ ADPCM とは結果が違う
  • -
- -

これから実装すること

- -
    -
  • 一括読み込みを止める
  • -
  • ↑もしくは EngineeringIO を使う
  • -
  • 音が汚い
  • -
  • 最後のフラグメントが切れている → #drain()
  • -
- -

一次ライセンス

- -WARNING THIS PROGRAM LICENCE IS LGPL - -
-/*
- * adpcm.c  codex functions for MS_ADPCM data
- *          (hopefully) provides interoperability with
- *          Microsoft's ADPCM format, but, as usual,
- *          see LACK-OF-WARRANTY information below.
- *
- *      Copyright (C) 1999 Stanley J. Brooks <stabro@megsinet.net>
- *
- *   This library is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU Lesser General Public
- *   License as published by the Free Software Foundation; either
- *   version 2 of the License, or (at your option) any later version.
- *
- *   This library is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *   Lesser General Public License for more details.
- *
- *   You should have received a copy of the GNU Lesser General Public
- *   License along with this library; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
- - - - diff --git a/src/main/java/vavi/sound/adpcm/ms/readme.md b/src/main/java/vavi/sound/adpcm/ms/readme.md new file mode 100644 index 0000000..ddfef1b --- /dev/null +++ b/src/main/java/vavi/sound/adpcm/ms/readme.md @@ -0,0 +1,45 @@ +vavi.sound.adpcm.ms + +MS ADPCM フォーマット関連のクラスを提供します. + +## Status + +sox と同じ結果になったので完成とみなす。 + +## Tech-know + + * ACM の M$ ADPCM とは結果が違う + +## TODO + + * ~~datetime="111016">一括読み込みを止める~~ + * ~~datetime="111016">↑もしくは EngineeringIO を使う~~ + * ~~datetime="060124">音が汚い~~ + * ~~最後のフラグメントが切れている~~ → #drain() + +## TODO +``` +/* + * adpcm.c codex functions for MS_ADPCM data + * (hopefully) provides interoperability with + * Microsoft's ADPCM format, but, as usual, + * see LACK-OF-WARRANTY information below. + * + * Copyright (C) 1999 Stanley J. Brooks <stabro@megsinet.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +``` \ No newline at end of file diff --git a/src/main/java/vavi/sound/adpcm/package.html b/src/main/java/vavi/sound/adpcm/package.html deleted file mode 100644 index afdca31..0000000 --- a/src/main/java/vavi/sound/adpcm/package.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - -vavi.sound.adpcm - - - - - -

-ADPCM サウンド CODEC 関連のクラスを提供します. -

- -

これから実装すること

- -
    -
  • javax.sound.sampled.spi に組み込み
  • -
  • サンプリングレートの変換
  • -
  • Codec インターフェースの抜き出し
  • -
  • AdpcmInputStream/AdpcmOutputStream インターフェースの抜き出し
  • -
- - - - diff --git a/src/main/java/vavi/sound/adpcm/readme.md b/src/main/java/vavi/sound/adpcm/readme.md new file mode 100644 index 0000000..4000cc1 --- /dev/null +++ b/src/main/java/vavi/sound/adpcm/readme.md @@ -0,0 +1,10 @@ +# vavi.sound.adpcm + +ADPCM サウンド CODEC 関連のクラスを提供します. + +## TODO + + * javax.sound.sampled.spi に組み込み + * サンプリングレートの変換 + * ~~"060427 Codec インターフェースの抜き出し~~ + * ~~"060427 AdpcmInputStream/AdpcmOutputStream インターフェースの抜き出し~~ diff --git a/src/main/java/vavi/sound/adpcm/vox/package.html b/src/main/java/vavi/sound/adpcm/vox/package.html deleted file mode 100644 index 8596966..0000000 --- a/src/main/java/vavi/sound/adpcm/vox/package.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - -vavi.sound.adpcm.vox - - - - - -

-VOX ADPCM フォーマット関連のクラスを提供します. -

- -完成 - -

これから実装すること

- -
    -
  • decode x16???
  • -
  • -
- -

一次ライセンス

-
-/*  File: adpcm.c
-    Description: Routines to convert 12 bit linear samples to the
-       Dialogic or Oki ADPCM coding format.
-       I copied the algorithms out of the book "PC Telephony - The
-       complete guide to designing, building and programming systems
-       using Dialogic and Related Hardware" by Bob Edgar. pg 272-276.
-
-*/
-
- - - - diff --git a/src/main/java/vavi/sound/adpcm/vox/readme.md b/src/main/java/vavi/sound/adpcm/vox/readme.md new file mode 100644 index 0000000..5869bee --- /dev/null +++ b/src/main/java/vavi/sound/adpcm/vox/readme.md @@ -0,0 +1,24 @@ +# vavi.sound.adpcm.vox + +VOX ADPCM フォーマット関連のクラスを提供します. + +# Status + +完成 + +## TODO + + * ~~decode x16~~??? + +## License + +``` +/* File: adpcm.c + Description: Routines to convert 12 bit linear samples to the + Dialogic or Oki ADPCM coding format. + I copied the algorithms out of the book "PC Telephony - The + complete guide to designing, building and programming systems + using Dialogic and Related Hardware" by Bob Edgar. pg 272-276. + +*/ +``` \ No newline at end of file diff --git a/src/main/java/vavi/sound/adpcm/yamaha/package.html b/src/main/java/vavi/sound/adpcm/yamaha/package.html deleted file mode 100644 index ee0dea0..0000000 --- a/src/main/java/vavi/sound/adpcm/yamaha/package.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - -vavi.sound.adpcm.yamaha - - - - - -

-YAMAHA MA Chip ADPCM フォーマット関連のクラスを提供します. -

- -完成 - -

わかったこと

- -
    -
  • よう見たら YM2608 のコードと一緒やん、何が2年の研究やねん
  • -
  • -
- -

一次ライセンス

-
    -
  • 記載なし
  • -
- - - - diff --git a/src/main/java/vavi/sound/adpcm/yamaha/readme.md b/src/main/java/vavi/sound/adpcm/yamaha/readme.md new file mode 100644 index 0000000..4d7a335 --- /dev/null +++ b/src/main/java/vavi/sound/adpcm/yamaha/readme.md @@ -0,0 +1,14 @@ +# vavi.sound.adpcm.yamaha + +YAMAHA MA Chip ADPCM フォーマット関連のクラスを提供します. + +# Status + +完成 + +

+よう見たら YM2608 のコードと一緒やん、何が2年の研究やねん + +## License + +記載なし diff --git a/src/main/java/vavi/sound/adpcm/ym2608/package.html b/src/main/java/vavi/sound/adpcm/ym2608/readme.md similarity index 54% rename from src/main/java/vavi/sound/adpcm/ym2608/package.html rename to src/main/java/vavi/sound/adpcm/ym2608/readme.md index 1701e0b..e776d86 100644 --- a/src/main/java/vavi/sound/adpcm/ym2608/package.html +++ b/src/main/java/vavi/sound/adpcm/ym2608/readme.md @@ -1,165 +1,105 @@ - - - - - - - - - -vavi.sound.adpcm.ym2608 - - - - - -

+# vavi.sound.adpcm.ym2608 + YAMAHA (YM2608) ADPCM フォーマット関連のクラスを提供します. -

+ +## Status 完成(たぶん) -

これから実装すること

+## TODO + + * ~~なんか音がちっちゃーい~~ + * ~~OutputStream~~ + * C のリファレンスのほうがおかしい encode の i = のあたりが > 0 になることがある -
    -
  • なんか音がちっちゃーい
  • -
  • OutputStream
  • -
  • C のリファレンスのほうがおかしい encode の i = のあたりが > 0 になることがある
  • -
+## License -

一次ライセンス

-
    -
  • 記載なし
  • -
+記載なし -

ADPCMの基礎知識、およびYM2608のADPCM仕様

+## ADPCMの基礎知識、およびYM2608のADPCM仕様 -
+[source](http://hackipedia.org/Platform/Sega/Genesis/hardware,%20FM%20synthesis,%20YM2608/html/adpcm.html) + +### ◆ ADPCM -

◆ ADPCM

-

ADPCMはMPEGと違い、リニアPCMデータに対して1サンプルの振幅情報を圧縮する方式である。 ADPCMはサンプル間の差分を用いてデータ圧縮を行うという基本は変わらないが、コーデックの種類は多数存在し、YM2608のADPCM仕様もそのコーデックの1つである。 多くのコーデックは1サンプルのデータを2~4ビットに変換し、このADPCM化されたデータは完全に元の波形に戻る事は無く、コーデックの性能は「元波形の再現性」に現れる。 -

-

+ 16ビットのリニアPCMの場合、前サンプルとの差分を表現するには最大16ビット分の情報が必要となるが、これをそのまま記録(DPCM形式)したのではデータを小さくする事ができない。 そこでADPCMは「差分の精度を犠牲」にする事でデータを圧縮する。 具体的にはステップサイズをコーデックのエンコード演算ルールに従い動的変化させ、各差分値を2~4ビットの精度へ変換する処理である。 -

-

+ たとえばYM2608のADPCMでは4ビットの情報を持つので、ステップサイズにて分割された予測される振幅値は16種類存在する。 差分の正負で半分に分かれる為、実際に適用する予測値は8種類になり、エンコーダはこの8種類の予測値にもっとも近い場所を選びだす。 さらにこのうち2点の予測値は、よりLowerかよりHigherな予測値範囲外の意味として扱われるため、もっとも誤差の小さい予測値は6種類になる。 このように実際の差分値と予測値を比較しながら4ビットの値に変換処理を行うのがADPCMエンコードである。 -

-

+ ステップサイズとは1サンプルの分解能幅の事であり、ステップサイズが1の16ビットPCMは0~65535の65536段階で表現する。 ステップサイズが4の16ビットPCMは下位2ビットが0である0x0000~0xFFFCの16384段階で表現する。 ステップサイズが8192の場合、下位12ビットを0にした0x0000~0xF000の16段階で表現する。 強引な表現では、8ビットPCMはステップサイズが256の16ビットPCMという表現も可能である(ただし記録する範囲は上位8ビットだが)。 ステップサイズは量子化幅とも呼ばれる。 -

-

+ この為、ステップサイズを小さい値から大きい値に変換(ADPCMエンコード)した場合、差分値とステップサイズの境界値との誤差が大きいほど波形精度が悪くなる。 またステップサイズを元に戻す変換(ADPCMデコード)をした場合も、落とされた精度分の情報を再現する事ができない。 これが「元波形の再現性」と「差分の精度を犠牲」にするという意味である。 -

-

+ ステップサイズの動的変更は、各サンプル毎のコーデックエンコード演算によって更新される。 これはステップサイズまでデータとして記録すると、データ圧縮として効率的で無くなる為である。 エンコードの際に、元波形に対する適切なステップサイズが適宜使用されれば、その変換精度をなるべく高く保つ事が可能である。 これはそのエンコーダと、その波形予測ルールが優秀であるほど、ADPCM化されたデータの復元率が高くなる事を表す。 -

- -

◆ エンコード

-

+### ◆ エンコード + YM2608のADPCMアルゴリズムは比較的単純である。 YM2608のADPCMは16ビットのPCMを4ビットのADPCMデータに変換する。 またステップサイズは1/4単位の線形範囲による境界となる。 以下にこのエンコード手順を記載する。 -

-
    -
  1. 最初のサンプル X1 の取得と共に、予測値とステップサイズを初期化する。 -予測値の初期値 x0=0、ステップサイズの初期値 S0=127である。
  2. - -
  3. ADPCMデータ An を求めるには Xn と予測値 xn の差を演算し、差分 ⊿n を求める。
  4. - -
  5. ⊿n の絶対値を Sn で分割し( I=|⊿n|/Sn )、以下の表のようにIの演算結果から下位3ビットを決定する。
    -
    - - - - - - - - - - -
    AnL3L2L1I=|⊿n|/Snf
    0000I < 1/457/64
    10011/4 <= I < 2/457/64
    20102/4 <= I < 1/457/64
    30113/4 <= I < 4/457/64
    41004/4 <= I < 5/477/64
    51015/4 <= I < 6/4102/64
    61106/4 <= I < 7/4128/64
    71117/4 <= I153/64
    -
    -

    + + * 最初のサンプル X1 の取得と共に、予測値とステップサイズを初期化する。
    +予測値の初期値 x0=0、ステップサイズの初期値 S0=127である。 + * ADPCMデータ An を求めるには Xn と予測値 xn の差を演算し、差分 ⊿n を求める。
    +⊿n の絶対値を Sn で分割し( I=|⊿n|/Sn )、以下の表のようにIの演算結果から下位3ビットを決定する。
    + +|An|L3|L2|L1|I=|⊿n|/Sn|f| +|:--:|:--:|:--:|:--:|:--:|:--:| +|0|0|0|0|I < 1/4|57/64| +|1|0|0|1|1/4 <= I < 2/4|57/64| +|2|0|1|0|2/4 <= I < 1/4|57/64| +|3|0|1|1|3/4 <= I < 4/4|57/64| +|4|1|0|0|4/4 <= I < 5/4|77/64| +|5|1|0|1|5/4 <= I < 6/4|102/64| +|6|1|1|0|6/4 <= I < 7/4|128/64| +|7|1|1|1|7/4 <= I|153/64| + ⊿n と Sn の分割値 I が1/4以上かつ2/4未満であれば An は1というように求める。 つまり実際の差分が予測ステップサイズを超える精度になった場合(1/4未満や7/4以上)、予測値を大きく外れている可能性があり、これはデータ再現性に影響が出始める事を表す。 -

    -
  6. -
  7. ⊿n が正の場合は An の最上位ビット(ビット4)を0、負の場合は1にする。
  8. - -
  9. 予測値 x(n+1) を求める。予測値の更新には An の各ビット値と以下の式を用いて求める。
    -
    + * ⊿n が正の場合は An の最上位ビット(ビット4)を0、負の場合は1にする。 + * 予測値 x(n+1) を求める。予測値の更新には An の各ビット値と以下の式を用いて求める。
    +```x x(n+1) = ( 1-2xL4 ) x ( L3 + L2/2 + L1/4 + 1/8 ) x ⊿n + xn -
    -
  10. - -
  11. ステップサイズ S(n+1) を求める。ステップサイズの更新には、An の下位3ビットと上記表の f との関係を用いて求める。
    -
    +``` + * ステップサイズ S(n+1) を求める。ステップサイズの更新には、An の下位3ビットと上記表の f との関係を用いて求める。
    +``` S(n+1) = f( An ) x Sn -
    -
  12. +``` + * ステップサイズ Sn を飽和する。YM2608のADPCMステップサイズは最小127、最大24576と決められている。 + * データの終端まで2~7を繰り返す。 -
  13. ステップサイズ Sn を飽和する。YM2608のADPCMステップサイズは最小127、最大24576と決められている。
  14. +## ◆ デコード -
  15. データの終端まで2~7を繰り返す。
  16. -
- -

◆ デコード

-

エンコードの5と6が予測値とステップサイズを求める式となり、予測値 xn が復元値 Xn になる。 -

-
    -
  1. 最初のADPCMサンプル A1 の取得と共に、予測値とステップサイズを初期化する。 -予測値の初期値 x0=0、ステップサイズの初期値 S0=127である。
  2. - -
  3. 予測値 x(n+1) を求める。予測値の更新にはエンコード同様 An の各ビット値と表を用いて求める。
  4. - -
  5. 予測値 x(n+1) を復元値 X(n) とする。
  6. - -
  7. 復元値 X(n) を-32768~32767の範囲に適宜クリッピングする。
  8. - -
  9. ステップサイズ S(n+1) を求める。ステップサイズの更新には、An の下位3ビットと上記表の f との関係を用いて求める。
  10. - -
  11. ステップサイズ S(n+1) を飽和する。YM2608のADPCMステップサイズは最小127、最大24576と決められている。
  12. - -
  13. ADPCMデータの終端まで2~6を繰り返す。
  14. -
-
- - - + * 最初のADPCMサンプル `A1` の取得と共に、予測値とステップサイズを初期化する。
+予測値の初期値 `x0=0`、ステップサイズの初期値 `S0=127`である。 + * 予測値 `x(n+1)` を求める。予測値の更新にはエンコード同様 `An` の各ビット値と表を用いて求める。 + * 予測値 `x(n+1)` を復元値 `X(n)` とする。 + * 復元値 `X(n)` を`-32768~32767`の範囲に適宜クリッピングする。 + * ステップサイズ `S(n+1)` を求める。ステップサイズの更新には、An の下位3ビットと上記表の f との関係を用いて求める。 + * ステップサイズ `S(n+1)` を飽和する。YM2608のADPCMステップサイズは最小127、最大24576と決められている。 + * ADPCMデータの終端まで2~6を繰り返す。 diff --git a/src/main/java/vavi/sound/mfi/package.html b/src/main/java/vavi/sound/mfi/package.html deleted file mode 100644 index 61cffbd..0000000 --- a/src/main/java/vavi/sound/mfi/package.html +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - -vavi.sound.mfi - - - - - -

-MFi サウンド関連のクラスを提供します. -

- -

概要

-

-{@link javax.sound.midi} パッケージとほぼ同じ構造をしています。 -使用法は {@link javax.sound.midi} を参考にしてください。 -

-

-{@link vavi.sound.mfi.MfiSystem.getSequencer()} で再生する場合は -システムプロパティ javax.sound.midi.Sequencer に "#Real Time Sequencer" -を明示するようにしてください。{@link vavi.sound.midi.VaviSequencer} が -デフォルトシーケンサになった場合 {@link vavi.sound.mfi.MfiSystem#getMetaEventListener()} -が重複して登録されてしまいます。 -

- -

これから実装すること

- -
    -
  • 特殊命令の実装
  • -
  • MfiFileFormat のヘッダ情報の扱いが未実装、メッセージにするか?ファイルフォーマットにするか?
  • -
  • 出てない音階がある
  • -
  • MfiSystem converter の取得法が他と違う
  • -
  • MfiSystem#main で鳴らない...
  • -
- -

一次ライセンス

-

-オリジナルのソースは見あたらないため -一次ライセンスを気にする必要は無いと思われますが、 -念のために記しておきます。 -

-open i-Melody Project -

- Academic Free License (AFL), - GNU Library or Lesser General Public License (LGPL) -

- - - diff --git a/src/main/java/vavi/sound/mfi/readme.md b/src/main/java/vavi/sound/mfi/readme.md new file mode 100644 index 0000000..9428f96 --- /dev/null +++ b/src/main/java/vavi/sound/mfi/readme.md @@ -0,0 +1,31 @@ +# vavi.sound.mfi + +MFi サウンド関連のクラスを提供します. + +## Abstract + +{@link javax.sound.midi} パッケージとほぼ同じ構造をしています。 +使用法は {@link javax.sound.midi} を参考にしてください。 + +{@link vavi.sound.mfi.MfiSystem.getSequencer()} で再生する場合は +システムプロパティ javax.sound.midi.Sequencer に "#Real Time Sequencer" +を明示するようにしてください。{@link vavi.sound.midi.VaviSequencer} が +デフォルトシーケンサになった場合 {@link vavi.sound.mfi.MfiSystem#getMetaEventListener()} +が重複して登録されてしまいます。 + +## TODO + + * 特殊命令の実装 + * ~~"030825" MfiFileFormat のヘッダ情報の扱いが未実装、メッセージにするか?ファイルフォーマットにするか?~~ → + * ~~"030825" 出てない音階がある~~ + * MfiSystem converter の取得法が他と違う + * ~~"090110">MfiSystem#main で鳴らない...~~ + +## License +オリジナルのソースは見あたらないため +一次ライセンスを気にする必要は無いと思われますが、 +念のために記しておきます。 + + * [open i-Melody Project](http://www.xucker.jpn.org/ood/java/imelody/") + * [Academic Free License (AFL)](http://opensource.org/licenses/academic.php") + * [GNU Library or Lesser General Public License (LGPL)](http://www.gnu.org/licenses/lgpl.html) diff --git a/src/main/java/vavi/sound/mfi/spi/package.html b/src/main/java/vavi/sound/mfi/spi/package.html deleted file mode 100644 index 0e846b5..0000000 --- a/src/main/java/vavi/sound/mfi/spi/package.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - -vavi.sound.mfi.spi - - - - - -

-MFi のサービスプロバイダのクラスを提供します. -

- -

これから実装すること

- -
    -
  • -
- - - - diff --git a/src/main/java/vavi/sound/mfi/spi/readme.md b/src/main/java/vavi/sound/mfi/spi/readme.md new file mode 100644 index 0000000..cdd0348 --- /dev/null +++ b/src/main/java/vavi/sound/mfi/spi/readme.md @@ -0,0 +1,5 @@ +# vavi.sound.mfi.spi + +MFi のサービスプロバイダのクラスを提供します. + +## TODO diff --git a/src/main/java/vavi/sound/mfi/vavi/HeaderChunk.java b/src/main/java/vavi/sound/mfi/vavi/HeaderChunk.java index 265fdba..8e7f79b 100644 --- a/src/main/java/vavi/sound/mfi/vavi/HeaderChunk.java +++ b/src/main/java/vavi/sound/mfi/vavi/HeaderChunk.java @@ -13,6 +13,7 @@ import java.io.OutputStream; import java.util.LinkedHashMap; import java.util.Map; +import java.util.logging.Level; import vavi.sound.mfi.InvalidMfiDataException; import vavi.sound.mfi.Sequence; @@ -180,11 +181,11 @@ public void writeTo(OutputStream os) // 1. check if (!isValid()) { -Debug.println("majorType: " + majorType); -Debug.println("minorType: " + minorType); -Debug.println("[sorc]: " + subChunks.get(SorcMessage.TYPE)); -Debug.println("[titl]: " + subChunks.get(TitlMessage.TYPE)); -Debug.println("[vers]: " + subChunks.get(VersMessage.TYPE)); +Debug.println(Level.FINE, "majorType: " + majorType); +Debug.println(Level.FINE, "minorType: " + minorType); +Debug.println(Level.FINE, "[sorc]: " + subChunks.get(SorcMessage.TYPE)); +Debug.println(Level.FINE, "[titl]: " + subChunks.get(TitlMessage.TYPE)); +Debug.println(Level.FINE, "[vers]: " + subChunks.get(VersMessage.TYPE)); throw new InvalidMfiDataException("fields are not filled"); } @@ -207,11 +208,11 @@ public void writeTo(OutputStream os) dos.writeByte(majorType); dos.writeByte(minorType); dos.writeByte(tracksCount); -Debug.println("mfiDataLength: " + mfiDataLength); -Debug.println("dataLength: " + dataLength); -Debug.println("majorType: " + majorType); -Debug.println("minorType: " + minorType); -Debug.println("numberTracks: " + tracksCount); +Debug.println(Level.FINE, "mfiDataLength: " + mfiDataLength); +Debug.println(Level.FINE, "dataLength: " + dataLength); +Debug.println(Level.FINE, "majorType: " + majorType); +Debug.println(Level.FINE, "minorType: " + minorType); +Debug.println(Level.FINE, "numberTracks: " + tracksCount); for (SubMessage subChunk : subChunks.values()) { subChunk.writeTo(os); @@ -239,21 +240,21 @@ public static HeaderChunk readFrom(InputStream is) // 1.2 length headerChunk.mfiDataLength = dis.readInt(); -Debug.println("mfiDataLength: " + headerChunk.mfiDataLength); +Debug.println(Level.FINE, "mfiDataLength: " + headerChunk.mfiDataLength); // 1.3.1 offset to "trac" or "adat" headerChunk.dataLength = dis.readUnsignedShort(); -Debug.println("dataLength: " + headerChunk.dataLength); +Debug.println(Level.FINE, "dataLength: " + headerChunk.dataLength); // 1.3.2.1 major type headerChunk.majorType = dis.readUnsignedByte(); -Debug.println("majorType: " + headerChunk.majorType); +Debug.println(Level.FINE, "majorType: " + headerChunk.majorType); // 1.3.2.2 minor type headerChunk.setMinorType(dis.readUnsignedByte()); -Debug.println("minorType: " + headerChunk.minorType); +Debug.println(Level.FINE, "minorType: " + headerChunk.minorType); // 1.3.3 number of tracks headerChunk.tracksCount = dis.readUnsignedByte(); -Debug.println("numberTracks: " + headerChunk.tracksCount); +Debug.println(Level.FINE, "numberTracks: " + headerChunk.tracksCount); // 1.4 header sub chunks long l = 0; diff --git a/src/main/java/vavi/sound/mfi/vavi/MetaEventAdapter.java b/src/main/java/vavi/sound/mfi/vavi/MetaEventAdapter.java index a7c681f..6d4272d 100644 --- a/src/main/java/vavi/sound/mfi/vavi/MetaEventAdapter.java +++ b/src/main/java/vavi/sound/mfi/vavi/MetaEventAdapter.java @@ -17,7 +17,7 @@ import vavi.sound.mfi.vavi.sequencer.MfiMessageStore; import vavi.sound.mfi.vavi.sequencer.UnknownVenderSequencer; import vavi.sound.mfi.vavi.track.MachineDependentMessage; -import vavi.sound.midi.MidiConstants; +import vavi.sound.midi.MidiConstants.MetaEvent; import vavi.sound.midi.MidiUtil; import vavi.sound.midi.VaviMidiDeviceProvider; import vavi.util.Debug; @@ -66,8 +66,8 @@ public void open() { */ public void meta(javax.sound.midi.MetaMessage message) { //Debug.println("type: " + message.getType()); - switch (message.getType()) { - case MidiConstants.META_MACHINE_DEPEND: // シーケンサ固有のメタイベント + switch (MetaEvent.valueOf(message.getType())) { + case META_MACHINE_DEPEND: // シーケンサ固有のメタイベント try { processSpecial(message); } catch (InvalidMfiDataException e) { @@ -80,13 +80,13 @@ public void meta(javax.sound.midi.MetaMessage message) { throw e; } break; - case MidiConstants.META_TEXT_EVENT: // テキスト・イベント - case MidiConstants.META_COPYRIGHT: // 著作権表示 - case MidiConstants.META_NAME: // シーケンス名またはトラック名 + case META_TEXT_EVENT: // テキスト・イベント + case META_COPYRIGHT: // 著作権表示 + case META_NAME: // シーケンス名またはトラック名 Debug.println("meta " + message.getType() + ": " + MidiUtil.getDecodedMessage(message.getData())); break; - case MidiConstants.META_END_OF_TRACK: // トラックの終わり - case MidiConstants.META_TEMPO: // テンポ設定 + case META_END_OF_TRACK: // トラックの終わり + case META_TEMPO: // テンポ設定 Debug.println(Level.FINE, "this handler ignore meta: " + message.getType()); break; default: diff --git a/src/main/java/vavi/sound/mfi/vavi/MfiContext.java b/src/main/java/vavi/sound/mfi/vavi/MfiContext.java index c35155e..1cd70c1 100644 --- a/src/main/java/vavi/sound/mfi/vavi/MfiContext.java +++ b/src/main/java/vavi/sound/mfi/vavi/MfiContext.java @@ -26,7 +26,7 @@ import vavi.sound.mfi.MfiEvent; import vavi.sound.mfi.vavi.track.NopMessage; import vavi.sound.mfi.vavi.track.TempoMessage; -import vavi.sound.midi.MidiConstants; +import vavi.sound.midi.MidiConstants.MetaEvent; import vavi.sound.midi.MidiUtil; import vavi.util.Debug; @@ -331,7 +331,7 @@ public void setMidiSequence(Sequence midiSequence) { for (int i = 0; i < midiTracks[t].size(); i++) { javax.sound.midi.MidiMessage midiMessage = midiTracks[t].get(i).getMessage(); if (midiMessage instanceof MetaMessage && - ((MetaMessage) midiMessage).getType() == MidiConstants.META_TEMPO) { + ((MetaMessage) midiMessage).getType() == MetaEvent.META_TEMPO.number()) { MetaMessage metaMessage = (MetaMessage) midiMessage; byte data[] = metaMessage.getData(); diff --git a/src/main/java/vavi/sound/mfi/vavi/MfiConvertible.java b/src/main/java/vavi/sound/mfi/vavi/MfiConvertible.java index ecb0682..15cec59 100644 --- a/src/main/java/vavi/sound/mfi/vavi/MfiConvertible.java +++ b/src/main/java/vavi/sound/mfi/vavi/MfiConvertible.java @@ -17,20 +17,24 @@ /** * MfiConvertible *

- * 今のところ実装クラスは bean でなければならない. - * (引数なしのコンストラクタがあること) + * Currently, an implementation class of this interface should be an bean. + * (means having a contractor without argument) *

+ *
+ * properties file ... "/vavi/sound/mfi/vavi/vavi.properties"
+ * name prefix ... "midi."
+ * 
* * @author Naohide Sano (nsano) * @version 0.00 030905 nsano initial version
*/ public interface MfiConvertible { - /** TODO 実装法いまいち,BeanUtil 等が使えないか? */ + /** */ MfiEvent[] getMfiEvents(MidiEvent midiEvent, MfiContext context) throws InvalidMfiDataException; - /** */ + /** factory */ static final PrefixedPropertiesFactory factory = new PrefixedClassPropertiesFactory<>("/vavi/sound/mfi/vavi/vavi.properties", "midi."); } diff --git a/src/main/java/vavi/sound/mfi/vavi/SubMessage.java b/src/main/java/vavi/sound/mfi/vavi/SubMessage.java index 5b4815a..64a096b 100644 --- a/src/main/java/vavi/sound/mfi/vavi/SubMessage.java +++ b/src/main/java/vavi/sound/mfi/vavi/SubMessage.java @@ -176,7 +176,7 @@ public void writeTo(OutputStream os) throws IOException { dos.writeBytes(getSubType()); dos.writeShort(getDataLength()); dos.write(getData(), 0, getDataLength()); -Debug.println(this); +Debug.println(Level.FINE, this); } /** @@ -214,7 +214,7 @@ public static SubMessage readFrom(InputStream is) try { subChunk = constructor.newInstance(subType, subData); } catch (Exception e) { -Debug.printStackTrace(e); +Debug.printStackTrace(Level.SEVERE, e); throw new IllegalStateException(e); } } else { @@ -231,7 +231,7 @@ public static SubMessage readFrom(InputStream is) }; } -Debug.println(subChunk); +Debug.println(Level.FINE, subChunk); return subChunk; } @@ -265,15 +265,15 @@ public static SubMessage readFrom(InputStream is) String value = props.getProperty("encoding.write"); if (value != null) { writingEncoding = value; -Debug.println("write encoding: " + writingEncoding); +Debug.println(Level.FINE, "write encoding: " + writingEncoding); } value = props.getProperty("encoding.read"); if (value != null) { readingEncoding = value; -Debug.println("read encoding: " + readingEncoding); +Debug.println(Level.FINE, "read encoding: " + readingEncoding); } } catch (Exception e) { -Debug.printStackTrace(e); +Debug.printStackTrace(Level.SEVERE, e); throw new IllegalStateException(e); } } diff --git a/src/main/java/vavi/sound/mfi/vavi/TrackMessage.java b/src/main/java/vavi/sound/mfi/vavi/TrackMessage.java index 237b916..8a4446c 100644 --- a/src/main/java/vavi/sound/mfi/vavi/TrackMessage.java +++ b/src/main/java/vavi/sound/mfi/vavi/TrackMessage.java @@ -68,13 +68,13 @@ public TrackMessage(int trackNumber, Track track) { /** */ public void setNoteLength(int noteLength) { this.noteLength = noteLength; -Debug.println("noteLength: " + noteLength); +Debug.println(Level.FINE, "noteLength: " + noteLength); } /** */ public void setExst(int exst) { this.exst = exst; -Debug.println("exst: " + exst); +Debug.println(Level.FINE, "exst: " + exst); } /** @@ -87,7 +87,7 @@ public void writeTo(OutputStream os) throws IOException { dos.writeBytes(TYPE); dos.writeInt(getDataLength()); -Debug.println("track: " + trackNumber + ": " + getDataLength()); +Debug.println(Level.FINE, "track: " + trackNumber + ": " + getDataLength()); for (int j = 0; j < track.size(); j++) { MfiEvent event = track.get(j); MfiMessage message = event.getMessage(); @@ -114,8 +114,8 @@ public int getDataLength() { trackLength += message.getLength(); } } catch (RuntimeException e) { - Debug.printStackTrace(e); - Debug.println("j: " + j + ", track.size: " + track.size() + ", " + track.get(j)); + Debug.printStackTrace(Level.SEVERE, e); + Debug.println(Level.SEVERE, "j: " + j + ", track.size: " + track.size() + ", " + track.get(j)); throw e; } } @@ -152,7 +152,7 @@ public void readFrom(InputStream is) // length int trackLength = dis.readInt(); -Debug.println("trackLength[" + trackNumber + "]: " + trackLength); +Debug.println(Level.FINE, "trackLength[" + trackNumber + "]: " + trackLength); // events int l = 0; @@ -290,7 +290,7 @@ public static MfiMessage getMessage(int delta, noteMessageConstructor2 = clazz.getConstructor(Integer.TYPE, Integer.TYPE, Integer.TYPE, Integer.TYPE); } } catch (Exception e) { -Debug.printStackTrace(e); +Debug.printStackTrace(Level.SEVERE, e); throw new IllegalStateException(e); } } @@ -361,7 +361,7 @@ public static MfiMessage getMessage(int delta, } } } catch (Exception e) { -Debug.printStackTrace(e); +Debug.printStackTrace(Level.SEVERE, e); throw new IllegalStateException(e); } } @@ -430,7 +430,7 @@ public static MfiMessage getMessage(int delta, } } catch (Exception e) { -Debug.printStackTrace(e); +Debug.printStackTrace(Level.SEVERE, e); throw new IllegalStateException(e); } } @@ -501,7 +501,7 @@ public static MfiMessage getMessage(int delta, } } } catch (Exception e) { -Debug.printStackTrace(e); +Debug.printStackTrace(Level.SEVERE, e); throw new IllegalStateException(e); } } @@ -559,7 +559,7 @@ public static MfiMessage getMessage(int delta, } } catch (Exception e) { -Debug.printStackTrace(e); +Debug.printStackTrace(Level.SEVERE, e); throw new IllegalStateException(e); } } diff --git a/src/main/java/vavi/sound/mfi/vavi/VaviMfiFileWriter.java b/src/main/java/vavi/sound/mfi/vavi/VaviMfiFileWriter.java index 953725c..3c05138 100644 --- a/src/main/java/vavi/sound/mfi/vavi/VaviMfiFileWriter.java +++ b/src/main/java/vavi/sound/mfi/vavi/VaviMfiFileWriter.java @@ -127,14 +127,14 @@ public int write(Sequence in, int fileType, OutputStream out) try { ff.writeTo(out); } catch (InvalidMfiDataException e) { -Debug.printStackTrace(e); +Debug.printStackTrace(Level.WARNING, e); return 0; } return ff.getByteLength(); } - /** {@link #write(Sequence, int, OutputStream)} に委譲 */ + /** delegate to {@link #write(Sequence, int, OutputStream)} */ public int write(Sequence in, int fileType, File out) throws IOException { @@ -152,34 +152,34 @@ public int write(Sequence in, int fileType, File out) String value = props.getProperty("format.type.major"); if (value != null) { defaultMajorType = Integer.parseInt(value); -Debug.println("major: " + defaultMajorType); +Debug.println(Level.FINE, "major: " + defaultMajorType); } value = props.getProperty("format.type.minor"); if (value != null) { defaultMinorType = Integer.parseInt(value); -Debug.println("minor: " + defaultMinorType); +Debug.println(Level.FINE, "minor: " + defaultMinorType); } value = props.getProperty("format.header.titl"); if (value != null) { defaultTitle = value; -Debug.println("titl: " + defaultTitle); +Debug.println(Level.FINE, "titl: " + defaultTitle); } value = props.getProperty("format.header.prot"); if (value != null) { defaultCreator = value; -Debug.println("prot: " + defaultCreator); +Debug.println(Level.FINE, "prot: " + defaultCreator); } value = props.getProperty("format.header.vers"); if (value != null) { defaultVersion = value; -Debug.println("vers: " + defaultVersion); +Debug.println(Level.FINE, "vers: " + defaultVersion); } } catch (Exception e) { -Debug.printStackTrace(e); +Debug.printStackTrace(Level.SEVERE, e); throw new IllegalStateException(e); } } diff --git a/src/main/java/vavi/sound/mfi/vavi/VaviMidiConverter.java b/src/main/java/vavi/sound/mfi/vavi/VaviMidiConverter.java index 0ee1d22..44117ca 100644 --- a/src/main/java/vavi/sound/mfi/vavi/VaviMidiConverter.java +++ b/src/main/java/vavi/sound/mfi/vavi/VaviMidiConverter.java @@ -156,9 +156,9 @@ protected vavi.sound.mfi.Sequence convert(Sequence midiSequence, int fileType) // 0xb0 10: panpot if ((command & 0xf0) == 0xb0) { - key = "midi.short." + (command & 0xf0) + "." + data1; + key = "short." + (command & 0xf0) + "." + data1; } else { - key = "midi.short." + (command & 0xf0); + key = "short." + (command & 0xf0); } } else if (midiMessage instanceof SysexMessage) { @@ -176,7 +176,7 @@ protected vavi.sound.mfi.Sequence convert(Sequence midiSequence, int fileType) mfiContext.setTrackUsed(0, true); mfiTrackNumber = 0; - key = "midi.sysex." + data[0]; + key = "sysex." + data[0]; } else if (midiMessage instanceof MetaMessage) { // 1 -> ProtInfo // 2 -> CopyInfo @@ -196,13 +196,18 @@ protected vavi.sound.mfi.Sequence convert(Sequence midiSequence, int fileType) mfiContext.setTrackUsed(0, true); mfiTrackNumber = 0; - key = "midi.meta." + meta; + key = "meta." + meta; } // convert try { MfiConvertible converter = MfiConvertible.factory.get(key); - if (converter instanceof EndOfTrackMessage) { // TODO ??? + if (converter == null) { +if (!uc.contains(key)) { + Debug.println(Level.WARNING, "no converter for: [" + key + "]"); + uc.add(key); +} + } else if (converter instanceof EndOfTrackMessage) { // TODO ??? // converted MfiEvent[] mfiEvents = converter.getMfiEvents(midiEvent, mfiContext); for (int t = 0; t < mfiEvents.length && t < maxTracks; t++) { @@ -249,12 +254,7 @@ protected vavi.sound.mfi.Sequence convert(Sequence midiSequence, int fileType) } } } catch (IllegalArgumentException e) { -if (!uc.contains(key)) { - Debug.println(Level.WARNING, "no converter for: " + key); - uc.add(key); -} -//} else { -//Debug.println("converter: " + StringUtil.getClassName(converter.getClass())); + Debug.println(Level.WARNING, e); } } diff --git a/src/main/java/vavi/sound/mfi/vavi/VaviSequencer.java b/src/main/java/vavi/sound/mfi/vavi/VaviSequencer.java index 2eb8982..2af7f34 100644 --- a/src/main/java/vavi/sound/mfi/vavi/VaviSequencer.java +++ b/src/main/java/vavi/sound/mfi/vavi/VaviSequencer.java @@ -84,7 +84,7 @@ public boolean isOpen() { return midiSequencer.isOpen(); } - /** ADPCM sequencer */ + /** ADPCM sequencer, TODO should be {@link javax.sound.midi.Transmitter} */ private javax.sound.midi.MetaEventListener mea = new MetaEventAdapter(); /* */ diff --git a/src/main/java/vavi/sound/mfi/vavi/header/CopyMessage.java b/src/main/java/vavi/sound/mfi/vavi/header/CopyMessage.java index 91b3def..8eb479e 100644 --- a/src/main/java/vavi/sound/mfi/vavi/header/CopyMessage.java +++ b/src/main/java/vavi/sound/mfi/vavi/header/CopyMessage.java @@ -20,6 +20,7 @@ import vavi.sound.mfi.vavi.MidiContext; import vavi.sound.mfi.vavi.MidiConvertible; import vavi.sound.midi.MidiConstants; +import vavi.sound.midi.MidiConstants.MetaEvent; import vavi.sound.midi.MidiUtil; @@ -75,7 +76,7 @@ public MidiEvent[] getMidiEvents(MidiContext context) throws InvalidMidiDataExce MetaMessage metaMessage = new MetaMessage(); - metaMessage.setMessage(MidiConstants.META_COPYRIGHT, // 著作権表示 + metaMessage.setMessage(MetaEvent.META_COPYRIGHT.number(), getData(), getDataLength()); return new MidiEvent[] { diff --git a/src/main/java/vavi/sound/mfi/vavi/header/ProtMessage.java b/src/main/java/vavi/sound/mfi/vavi/header/ProtMessage.java index 100d96a..531d398 100644 --- a/src/main/java/vavi/sound/mfi/vavi/header/ProtMessage.java +++ b/src/main/java/vavi/sound/mfi/vavi/header/ProtMessage.java @@ -18,6 +18,7 @@ import vavi.sound.mfi.vavi.MidiContext; import vavi.sound.mfi.vavi.MidiConvertible; import vavi.sound.midi.MidiConstants; +import vavi.sound.midi.MidiConstants.MetaEvent; import vavi.sound.midi.MidiUtil; @@ -80,7 +81,7 @@ public MidiEvent[] getMidiEvents(MidiContext context) MetaMessage metaMessage = new MetaMessage(); - metaMessage.setMessage(MidiConstants.META_TEXT_EVENT, // テキスト + metaMessage.setMessage(MetaEvent.META_TEXT_EVENT.number(), getData(), getDataLength()); diff --git a/src/main/java/vavi/sound/mfi/vavi/header/TitlMessage.java b/src/main/java/vavi/sound/mfi/vavi/header/TitlMessage.java index 69f2a9d..af9d129 100644 --- a/src/main/java/vavi/sound/mfi/vavi/header/TitlMessage.java +++ b/src/main/java/vavi/sound/mfi/vavi/header/TitlMessage.java @@ -20,6 +20,7 @@ import vavi.sound.mfi.vavi.MidiContext; import vavi.sound.mfi.vavi.MidiConvertible; import vavi.sound.midi.MidiConstants; +import vavi.sound.midi.MidiConstants.MetaEvent; import vavi.sound.midi.MidiUtil; @@ -91,7 +92,7 @@ public MidiEvent[] getMidiEvents(MidiContext context) MetaMessage metaMessage = new MetaMessage(); - metaMessage.setMessage(MidiConstants.META_NAME, // シーケンス名/トラック名 + metaMessage.setMessage(MetaEvent.META_NAME.number(), // シーケンス名/トラック名 getData(), getDataLength()); diff --git a/src/main/java/vavi/sound/mfi/vavi/header/package.html b/src/main/java/vavi/sound/mfi/vavi/header/package.html deleted file mode 100644 index 7d2a5f6..0000000 --- a/src/main/java/vavi/sound/mfi/vavi/header/package.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - -vavi.sound.mfi.vavi.header - - - - - -

-MFi Header の Sub Chunk (SubMessage の派生クラス)を提供します. -

- -

これから実装すること

- -
    -
  • thrd 3D定位機能利用情報
  • -
- - - - diff --git a/src/main/java/vavi/sound/mfi/vavi/header/readme.md b/src/main/java/vavi/sound/mfi/vavi/header/readme.md new file mode 100644 index 0000000..0c0c5e7 --- /dev/null +++ b/src/main/java/vavi/sound/mfi/vavi/header/readme.md @@ -0,0 +1,7 @@ +# vavi.sound.mfi.vavi.header + +MFi Header の Sub Chunk (SubMessage の派生クラス)を提供します. + +## TODO + + * thrd 3D定位機能利用情報 diff --git a/src/main/java/vavi/sound/mfi/vavi/mitsubishi/MitsubishiSequencer.java b/src/main/java/vavi/sound/mfi/vavi/mitsubishi/MitsubishiSequencer.java index 8174be7..aaedcc2 100644 --- a/src/main/java/vavi/sound/mfi/vavi/mitsubishi/MitsubishiSequencer.java +++ b/src/main/java/vavi/sound/mfi/vavi/mitsubishi/MitsubishiSequencer.java @@ -16,6 +16,10 @@ /** * Mitsubishi System exclusive message sequencer. + *
+ * properties file ... "/vavi/sound/mfi/vavi/mitsubishi/mitsubishi.properties"
+ * name prefix ... "function."
+ * 
* * @author Naohide Sano (nsano) * @version 0.00 030618 nsano initial version
@@ -52,7 +56,8 @@ static AudioEngine getAudioEngine() { //------------------------------------------------------------------------- /** */ - private static MachineDependentFunction.Factory factory = new MachineDependentFunction.Factory("/vavi/sound/mfi/vavi/mitsubishi/mitsubishi.properties"); + private static MachineDependentFunction.Factory factory = + new MachineDependentFunction.Factory("/vavi/sound/mfi/vavi/mitsubishi/mitsubishi.properties"); } /* */ diff --git a/src/main/java/vavi/sound/mfi/vavi/mitsubishi/package.html b/src/main/java/vavi/sound/mfi/vavi/mitsubishi/package.html deleted file mode 100644 index ad3a396..0000000 --- a/src/main/java/vavi/sound/mfi/vavi/mitsubishi/package.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - -vavi.sound.mfi.vavi.mitsubishi - - - - - -

-三菱電機製固有のメッセージ処理クラスを提供します. -

- -

これから実装すること

- -
    -
  • -
- - - - diff --git a/src/main/java/vavi/sound/mfi/vavi/mitsubishi/readme.md b/src/main/java/vavi/sound/mfi/vavi/mitsubishi/readme.md new file mode 100644 index 0000000..4770d65 --- /dev/null +++ b/src/main/java/vavi/sound/mfi/vavi/mitsubishi/readme.md @@ -0,0 +1,5 @@ +# vavi.sound.mfi.vavi.mitsubishi + +三菱電機製固有のメッセージ処理クラスを提供します. + +## TODO diff --git a/src/main/java/vavi/sound/mfi/vavi/nec/NecSequencer.java b/src/main/java/vavi/sound/mfi/vavi/nec/NecSequencer.java index f0a2074..f49219a 100644 --- a/src/main/java/vavi/sound/mfi/vavi/nec/NecSequencer.java +++ b/src/main/java/vavi/sound/mfi/vavi/nec/NecSequencer.java @@ -17,6 +17,10 @@ /** * NEC System exclusive message processor. + *
+ * properties file ... "/vavi/sound/mfi/vavi/nec/nec.properties"
+ * name prefix ... "function."
+ * 
* * @author Naohide Sano (nsano) * @version 0.00 020703 nsano initial version
@@ -78,7 +82,8 @@ static AudioEngine getAudioEngine() { //------------------------------------------------------------------------- /** */ - private static MachineDependentFunction.Factory factory = new MachineDependentFunction.Factory("/vavi/sound/mfi/vavi/nec/nec.properties"); + private static MachineDependentFunction.Factory factory = + new MachineDependentFunction.Factory("/vavi/sound/mfi/vavi/nec/nec.properties"); } /* */ diff --git a/src/main/java/vavi/sound/mfi/vavi/nec/package.html b/src/main/java/vavi/sound/mfi/vavi/nec/package.html deleted file mode 100644 index e911939..0000000 --- a/src/main/java/vavi/sound/mfi/vavi/nec/package.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - -vavi.sound.mfi.vavi.nec - - - - - -

-NEC 固有のメッセージ処理クラスを提供します. -

- -

これから実装すること

- -
    -
  • -
- - - - diff --git a/src/main/java/vavi/sound/mfi/vavi/nec/readme.md b/src/main/java/vavi/sound/mfi/vavi/nec/readme.md new file mode 100644 index 0000000..c8e8b5b --- /dev/null +++ b/src/main/java/vavi/sound/mfi/vavi/nec/readme.md @@ -0,0 +1,5 @@ +# vavi.sound.mfi.vavi.nec + +NEC 固有のメッセージ処理クラスを提供します. + +## TODO diff --git a/src/main/java/vavi/sound/mfi/vavi/sequencer/AudioDataSequencer.java b/src/main/java/vavi/sound/mfi/vavi/sequencer/AudioDataSequencer.java index b670cde..d010fb8 100644 --- a/src/main/java/vavi/sound/mfi/vavi/sequencer/AudioDataSequencer.java +++ b/src/main/java/vavi/sound/mfi/vavi/sequencer/AudioDataSequencer.java @@ -13,6 +13,10 @@ /** * AudioData message sequencer. + *
+ * properties file ... "/vavi/sound/mfi/vavi/vavi.properties"
+ * name prefix ... "audioEngine.format."
+ * 
* * @author Naohide Sano (nsano) * @version 0.00 070119 nsano initial version
diff --git a/src/main/java/vavi/sound/mfi/vavi/sequencer/MachineDependentFunction.java b/src/main/java/vavi/sound/mfi/vavi/sequencer/MachineDependentFunction.java index 09460ff..b99693e 100644 --- a/src/main/java/vavi/sound/mfi/vavi/sequencer/MachineDependentFunction.java +++ b/src/main/java/vavi/sound/mfi/vavi/sequencer/MachineDependentFunction.java @@ -15,10 +15,14 @@ /** * Sub sequencer for machine dependent system exclusive message. *

- * 今のところ実装クラスは bean でなければならない。 - * (引数なしのコンストラクタがあること) - * {@link #process(MachineDependentMessage)} 関連はステートレスでなければならない。 + * Currently, an implementation class of this interface should be an bean. + * (means having a contractor without argument) + * {@link #process(MachineDependentMessage)} related should be state less. *

+ *
+ * properties file ... any
+ * name prefix ... "function."
+ * 
* @author Naohide Sano (nsano) * @version 0.00 030822 nsano initial version
*/ @@ -41,7 +45,7 @@ public interface MachineDependentFunction { void process(MachineDependentMessage message) throws InvalidMfiDataException; - /** */ + /** factory */ class Factory extends PrefixedClassPropertiesFactory { /** */ @@ -56,7 +60,7 @@ public MachineDependentFunction getFunction(String key) { } catch (IllegalArgumentException e) { Debug.println(key); Debug.printStackTrace(e); - return new UndefinedFunction(); // TODO should throw exception + return new UndefinedFunction(); // TODO should throw exception or not? } } } diff --git a/src/main/java/vavi/sound/mfi/vavi/sequencer/MachineDependentSequencer.java b/src/main/java/vavi/sound/mfi/vavi/sequencer/MachineDependentSequencer.java index c0662e1..e78df4c 100644 --- a/src/main/java/vavi/sound/mfi/vavi/sequencer/MachineDependentSequencer.java +++ b/src/main/java/vavi/sound/mfi/vavi/sequencer/MachineDependentSequencer.java @@ -14,6 +14,10 @@ /** * Sub sequencer for machine dependent system exclusive message. + *
+ * properties file ... "/vavi/sound/mfi/vavi/vavi.properties"
+ * name prefix ... "sequencer.vendor."
+ * 
* * @author Naohide Sano (nsano) * @version 0.00 020704 nsano initial version
@@ -23,11 +27,11 @@ public interface MachineDependentSequencer { /** for {@link MachineDependentSequencer} */ static final int META_FUNCTION_ID_MACHINE_DEPEND = 0x01; - /** */ + /** processes a message */ void sequence(MachineDependentMessage message) throws InvalidMfiDataException; - /** */ + /** factory */ static final PrefixedPropertiesFactory factory = new PrefixedClassPropertiesFactory<>("/vavi/sound/mfi/vavi/vavi.properties", "sequencer.vendor."); } diff --git a/src/main/java/vavi/sound/mfi/vavi/sequencer/package.html b/src/main/java/vavi/sound/mfi/vavi/sequencer/package.html deleted file mode 100644 index 341014e..0000000 --- a/src/main/java/vavi/sound/mfi/vavi/sequencer/package.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - -vavi.sound.mfi.vavi.sysex - - - - - -

-SysexMessage の派生クラスを提供します. -

- -

これから実装すること

- -
    -
  • まだまだ改良の余地あり
  • -
- - - - diff --git a/src/main/java/vavi/sound/mfi/vavi/sequencer/readme.md b/src/main/java/vavi/sound/mfi/vavi/sequencer/readme.md new file mode 100644 index 0000000..0cd9b60 --- /dev/null +++ b/src/main/java/vavi/sound/mfi/vavi/sequencer/readme.md @@ -0,0 +1,7 @@ +# vavi.sound.mfi.vavi.sysex + +SysexMessage の派生クラスを提供します. + +## TODO + + * まだまだ改良の余地あり diff --git a/src/main/java/vavi/sound/mfi/vavi/sharp/SharpSequencer.java b/src/main/java/vavi/sound/mfi/vavi/sharp/SharpSequencer.java index 62c5528..78a2b1d 100644 --- a/src/main/java/vavi/sound/mfi/vavi/sharp/SharpSequencer.java +++ b/src/main/java/vavi/sound/mfi/vavi/sharp/SharpSequencer.java @@ -16,6 +16,10 @@ /** * Sharp System exclusive message sequencer. + *
+ * properties file ... "/vavi/sound/mfi/vavi/sharp/sharp.properties"
+ * name prefix ... "function."
+ * 
* * @author Naohide Sano (nsano) * @version 0.00 051111 nsano initial version
@@ -50,7 +54,8 @@ static AudioEngine getAudioEngine() { //------------------------------------------------------------------------- /** */ - private static MachineDependentFunction.Factory factory = new MachineDependentFunction.Factory("/vavi/sound/mfi/vavi/sharp/sharp.properties"); + private static MachineDependentFunction.Factory factory = + new MachineDependentFunction.Factory("/vavi/sound/mfi/vavi/sharp/sharp.properties"); } /* */ diff --git a/src/main/java/vavi/sound/mfi/vavi/sharp/package.html b/src/main/java/vavi/sound/mfi/vavi/sharp/package.html deleted file mode 100644 index 45ba5fd..0000000 --- a/src/main/java/vavi/sound/mfi/vavi/sharp/package.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - -

-Sharp 製固有のメッセージ処理クラスを提供します. -

- -

これから実装すること

- -
    -
  • -
- - - - diff --git a/src/main/java/vavi/sound/mfi/vavi/sharp/readme.md b/src/main/java/vavi/sound/mfi/vavi/sharp/readme.md new file mode 100644 index 0000000..a2b91bc --- /dev/null +++ b/src/main/java/vavi/sound/mfi/vavi/sharp/readme.md @@ -0,0 +1,5 @@ +# vavi.sound.mfi.vavi.sharp + +Sharp 製固有のメッセージ処理クラスを提供します. + +## TODO diff --git a/src/main/java/vavi/sound/mfi/vavi/track/CuePointMessage.java b/src/main/java/vavi/sound/mfi/vavi/track/CuePointMessage.java index aac9e6f..69c8f47 100644 --- a/src/main/java/vavi/sound/mfi/vavi/track/CuePointMessage.java +++ b/src/main/java/vavi/sound/mfi/vavi/track/CuePointMessage.java @@ -13,7 +13,7 @@ import vavi.sound.mfi.ShortMessage; import vavi.sound.mfi.vavi.MidiContext; import vavi.sound.mfi.vavi.MidiConvertible; -import vavi.sound.midi.MidiConstants; +import vavi.sound.midi.MidiConstants.MetaEvent; /** @@ -98,7 +98,7 @@ public MidiEvent[] getMidiEvents(MidiContext context) throws InvalidMidiDataExce String text = start ? "start" : "stop"; - metaMessage.setMessage(MidiConstants.META_QUE_POINT, // キューポイント + metaMessage.setMessage(MetaEvent.META_QUE_POINT.number(), // キューポイント text.getBytes(), text.getBytes().length); return new MidiEvent[] { diff --git a/src/main/java/vavi/sound/mfi/vavi/track/MachineDependentMessage.java b/src/main/java/vavi/sound/mfi/vavi/track/MachineDependentMessage.java index 85d4b16..90340cb 100644 --- a/src/main/java/vavi/sound/mfi/vavi/track/MachineDependentMessage.java +++ b/src/main/java/vavi/sound/mfi/vavi/track/MachineDependentMessage.java @@ -10,6 +10,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.Serializable; +import java.util.logging.Level; import javax.sound.midi.InvalidMidiDataException; import javax.sound.midi.MetaMessage; @@ -102,7 +103,7 @@ public static MachineDependentMessage readFrom(int delta, int status, int data1, // 5 vendor | carrier // 6 // 7 -Debug.printf("MachineDepend: %02x, %02x, %02x %02x %02x %02x %02x\n", data[0], data[5], data[6], data[7], (data.length > 8 ? data[8] : 0), (data.length > 9 ? data[9] : 0), (data.length > 10 ? data[10] : 0)); +Debug.printf(Level.FINE, "MachineDepend: %02x, %02x, %02x %02x %02x %02x %02x\n", data[0], data[5], data[6], data[7], (data.length > 8 ? data[8] : 0), (data.length > 9 ? data[9] : 0), (data.length > 10 ? data[10] : 0)); MachineDependentMessage message = new MachineDependentMessage(data); return message; } diff --git a/src/main/java/vavi/sound/mfi/vavi/track/package.html b/src/main/java/vavi/sound/mfi/vavi/track/package.html deleted file mode 100644 index b65722b..0000000 --- a/src/main/java/vavi/sound/mfi/vavi/track/package.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - -vavi.sound.mfi.vavi.system - - - - - -

-SysexMessage の派生クラスを提供します. -

- -

Δタイム

- -
  • テンポ ... 1 分間の 4 分音符の数 -
  • タイムベース ... 4 分音符の分解能 = PPQ (Parts ...), TpQN (Tick par Quarter Note) -
    -        1Δ = 60[s] / テンポ / タイムベース;
    -
    - -

    これから実装すること

    - -
      -
    • Δ > 255 の Note の取り扱い
    • -

      - たとえば音調 380 (voice = 1) -

      - - - - - - - - - - - - - - - - - -
      deltavoicegateTime説明
      -12 + 10 + 1 = 13
      22-
      103-
      01max(380 - 13, 255) = 255voice が 1 ラウンドしたあとに?
      - - PsmPlayer は飛ばした分を最初のΔから引いている -
    • MFi 5.0 拡張用情報
    • -
    - - - - diff --git a/src/main/java/vavi/sound/mfi/vavi/track/readme.md b/src/main/java/vavi/sound/mfi/vavi/track/readme.md new file mode 100644 index 0000000..70564e9 --- /dev/null +++ b/src/main/java/vavi/sound/mfi/vavi/track/readme.md @@ -0,0 +1,28 @@ +# vavi.sound.mfi.vavi.system + +SysexMessage の派生クラスを提供します. + +### Δタイム + + * テンポ ... 1 分間の 4 分音符の数 + * タイムベース ... 4 分音符の分解能 = PPQ (Parts ...), TpQN (Tick par Quarter Note) +``` + 1Δ = 60[s] / テンポ / タイムベース; +``` + +## TODO + + * Δ > 255 の Note の取り扱い + + たとえば音調 380 (voice = 1) + +|delta|voice|gateTime|説明| +|:-:|:-:|:-:|:-:| +|-|1|2 + 10 + 1 = 13|| +|2|2|-|| +|10|3|-|| +|0|1|max(380 - 13, 255) = 255|voice が 1 ラウンドしたあとに?| + + PsmPlayer は飛ばした分を最初のΔから引いている + + * MFi 5.0 拡張用情報 diff --git a/src/main/java/vavi/sound/midi/BasicMidiFileReader.java b/src/main/java/vavi/sound/midi/BasicMidiFileReader.java index 1d9469f..661aeb4 100644 --- a/src/main/java/vavi/sound/midi/BasicMidiFileReader.java +++ b/src/main/java/vavi/sound/midi/BasicMidiFileReader.java @@ -26,8 +26,7 @@ /** - * BasicMidiFileReader. - * 継承したクラスで {@link #getSequence(InputStream)} を実装してください。 + * Should implement {@link #getSequence(InputStream)} at your subclass. * * @author Naohide Sano (nsano) * @version 0.00 041222 nsano initial version
    @@ -35,8 +34,8 @@ public abstract class BasicMidiFileReader extends MidiFileReader { /** - * 継承したクラスで実装した {@link #getSequence(InputStream)} で - * 実装したタイプから変換された MIDI Sequence を取得します。 + * Gets MIDI Sequence converted by a method {@link #getSequence(InputStream)} + * implemented in a sub class. * @param stream a midi stream * @throws IOException when the I/O does not support marking. */ @@ -49,6 +48,7 @@ public MidiFileFormat getMidiFileFormat(InputStream stream) ByteArrayOutputStream os = new ByteArrayOutputStream(); MidiSystem.write(midiSequence, 0, os); ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray()); +//Debug.println("temporary midi:\n" + StringUtil.getDump(os.toByteArray(), 128)); MidiFileFormat midiFF = MidiSystem.getMidiFileFormat(is); return midiFF; } diff --git a/src/main/java/vavi/sound/midi/BasicMidiFileWriter.java b/src/main/java/vavi/sound/midi/BasicMidiFileWriter.java index 8b2bc8b..1f71bc4 100644 --- a/src/main/java/vavi/sound/midi/BasicMidiFileWriter.java +++ b/src/main/java/vavi/sound/midi/BasicMidiFileWriter.java @@ -16,9 +16,9 @@ /** * BasicMidiFileWriter. - * - * @caution {@link javax.sound.midi.MidiSystem} は使っちゃだめ! - * + *

    + * !!!caution don't use {@link javax.sound.midi.MidiSystem} in this class. + *

    * @author Naohide Sano (nsano) * @version 0.00 041223 nsano initial version
    */ diff --git a/src/main/java/vavi/sound/midi/MidiConstants.java b/src/main/java/vavi/sound/midi/MidiConstants.java index 8df7356..9daba0c 100644 --- a/src/main/java/vavi/sound/midi/MidiConstants.java +++ b/src/main/java/vavi/sound/midi/MidiConstants.java @@ -7,7 +7,10 @@ package vavi.sound.midi; import java.io.IOException; +import java.util.Arrays; +import java.util.NoSuchElementException; import java.util.Properties; +import java.util.logging.Level; import vavi.util.Debug; @@ -20,11 +23,10 @@ */ public final class MidiConstants { - /** */ private MidiConstants() { } - /** */ + /** instrument names */ private static Properties props = new Properties(); /** */ @@ -40,211 +42,238 @@ public static String getInstrumentName(int index) { // グラムがすべてのメタ・イベントをサポートしなければならないということで // はない。最初に定義されたメタ・イベントには以下のものがある。 - /** - *
    -     * FF 00 02 ssss  [シーケンス・ナンバー]
    -     * 
    - * このオプション・イベントは、トラックの冒頭、任意の 0 でないデルタ・タイ - * ムの前で、かつ任意の転送可能な MIDI イベントの前に置かれなければならず - * 、これがシーケンスのナンバーを特定する。このトラック中のナンバーは - * 1987 年夏の MMA ミーティングで協議された新 Cue メッセージの中のシーケンス - * ・ナンバーに対応する。これは、フォーマット 2 の MIDI ファイルにおいては - * 、各々の「パターン」を識別することによって、Cue メッセージを用いている - * 「ソング」シーケンスがパターンを参照できるようにするために用いられる。 - * ID ナンバーが省略されているときは、そのシーケンスのファイル中での位置 - * [訳注:先頭から何番目のシーケンスか]がデフォールトとして用いられる。 - * フォーマット 0 または 1 の MIDI ファイルにおいては、1つのシーケンスしか - * 含まれないため、このナンバーは第 1 の(つまり唯一の)トラックに含まれ - * ることになる。いくつかのマルチトラック・シーケンスの転送が必要な場合は - * 、各々が異なるシーケンス・ナンバーを持つフォーマット1のファイルのグル - * ープとして行われなければならない。 - */ - public static final int META_SEQUENCE_NO = 0x00; - - /** - *
    -     * FF 01 len text  [テキスト・イベント]
    -     * 
    - * 任意の大きさおよび内容のテキスト。トラックのいちばん初めに、トラック名 - * 、意図するオーケストレイション、その他ユーザがそこに置きたいと思う情報 - * を書いておくと良い。テキスト・イベントは、トラック中でその他の時に入れ - * て歌詞やキュー・ポイントの記述として用いることもできる。このイベント中 - * のテキストは、最大限の互換性を確保するために、印刷可能なアスキー・キャ - * ラクタでなければならない。しかし、高位ビットを用いる他のキャラクタ・コ - * ード(訳注:漢字コードのような 2 バイト・コードなど)も、拡張されたキャ - * ラクタ・セットをサポートする同じコンピュータ上の異なるプログラム間でフ - * ァイルを交換するために用いることができる。非アスキー・キャラクタをサポ - * ートしない機種上のプログラムは、このようなコードを無視しなければならな - * い。 - * - * (0.06 での追加事項) メタ・イベントのタイプ 01 から 0F までは様々なタ - * イプのテキスト・イベントのために予約されている。この各々は上記のテキス - * ト・イベントの特性と重複しているが、以下のように、異なる目的のために用 - * いられる。 - */ - public static final int META_TEXT_EVENT = 0x01; - - /** - *
    -     * FF 02 len text  [著作権表示]
    -     * 
    - * 著作権表示を、印刷可能なアスキー・テキストとして持つ。この表示には(C) - * の文字と、著作物発行年と、著作権所有者名とが含まれなければならない。ひ - * とつの MIDI ファイルに幾つかの楽曲がある時には、すべての著作権表示をこ - * のイベントに置いて、それがファイルの先頭に来るようにしなければならない - * 。このイベントは第1トラック・ブロックの最初のイベントとして、デルタ・ - * タイム = 0 で置かれなければならない。 - */ - public static final int META_COPYRIGHT = 0x02; - - /** - *
    -     * FF 03 len text  [シーケンス名またはトラック名]
    -     * 
    - * フォーマット 0 のトラック、もしくはフォーマット 1 のファイルの第 1 トラッ - * クにおいては、シーケンスの名称。その他の場合は、トラックの名称。 - */ - public static final int META_NAME = 0x03; - - /** - *
    -     * FF 04 len text  [楽器名]
    -     * 
    - * そのトラックで用いられるべき楽器編成の種類を記述する。 MIDI の冒頭に置 - * かれるメタ・イベントとともに用いて、どの MIDI チャネルにその記述が適用 - * されるかを特定することもある。あるいは、チャネルをこのイベント中のテキ - * ストで特定しても良い。 - */ - public static final int META_INSTRUMENT = 0x04; - - /** - *
    -     * FF 05 len text  [歌詞]
    -     * 
    - * 歌詞。一般的には、各音節がそのイベントのタイムから始まる独立した歌詞イ - * ベントとなる。 - */ - public static final int META_LYRICS = 0x05; - - /** - *
    -     * FF 06 len text  [マーカー]
    -     * 
    - * 通常フォーマット 0 のトラック、もしくはフォーマット 1 のファイルの第1ト - * ラックにある。リハーサル記号やセクション名のような、シーケンスのその時 - * 点の名称。(「First Verse」等) - */ - public static final int META_MARKER = 0x06; - - /** - *
    -     * FF 07 len text  [キュー・ポイント]
    -     * 
    - * スコアのその位置において、フィルム、ヴィデオ・スクリーン、あるいはステ - * ージ上で起こっていることの記述。(「車が家に突っ込む」「幕が開く」「女 - * は男に平手打ちを食わせる」等) - */ - public static final int META_QUE_POINT = 0x07; - - /** - *
    -     * FF 2F 00  [トラックの終わり]
    -     * 
    - * このイベントは省略することができない。これがあることによってトラックの - * 正しい終結点が明確になり、トラックが正確な長さを持つようになる。これは - * トラックがループになっていたり連結されていたりする時に必要である。 - */ - public static final int META_END_OF_TRACK = 0x2f; // 47 - - /** - *
    -     * FF 51 03 tttttt  [テンポ設定(単位は μsec / MIDI 四分音符)]
    -     * 
    - * このイベントはテンポ・チェンジを指示する。「μsec / MIDI 四分音符」は - * 言い換えれば「(μsec / MIDI クロック)の 24 分の 1」である。テンポを - * 「拍 / 時間」ではなく「時間 / 拍」によって与えることで、 SMPTE タイム・ - * コードや MIDI タイム・コードのような実時間ベースの同期プロトコルを用い - * て、絶対的に正確な長時間同期を得ることができる。このテンポ設定で得られ - * る正確さは、120 拍 / 分で 4 分の曲を終わった時に誤差が 500 μsec 以内 - * にとどまる、というものである。理想的には、これらのイベントは Cue の - * 上で MIDI クロックがある位置にのみ、おかれるべきである。このことは、ほか - * の同期デバイスとの互換性を保証しよう、少なくとも、その見込みを増やそう - * 、というもので、この結果、この形式で保存された拍子記号やテンポ・マップ - * は容易にほかのデバイスへ転送できることになる。 - */ - public static final int META_TEMPO = 0x51; // 81 - - /** - *
    -     * FF 54 05 hr mn se fr ff  [SMPTE オフセット(0.06 での追加 - SMPTE フォーマットの記述)]
    -     * 
    - * このイベントは、もしあれば、トラック・ブロックがスタートすることになっ - * ている SMPTE タイムを示す。これは、トラックの冒頭に置かれなければなら - * ない。すなわち、任意の 0 でないデルタ・タイムの前で、かつ任意の転送可能 - * な MIDI イベントの前である。時間は、 MIDI タイム・コードと全く同様に - * SMPTE フォーマットでエンコードされなければならない。フォーマット 1 のフ - * ァイルにおいては、 SMPTE オフセットはテンポ・マップとともにストアされ - * る必要があり、他のトラックにあっては意味をなさない。デルタ・タイムのた - * めに異なるフレーム分解能を指定している SMPTE ベースのトラックにおいて - * も、ff のフィールドは細分化されたフレーム(100 分の 1 フレーム単位)を - * 持っている。 - */ - public static final int META_SMPTE_OFFSERT = 0x54; // 84 - - /** - *
    -     * FF 58 04 nn dd cc bb  [拍子記号]
    -     * 
    - * 拍子記号は、4 つの数字で表現される。nn と dd は、記譜する時のように、拍子 - * 記号の分子と分母を表す。分母は 2 のマイナス乗である。すなわち、2 は四分 - * 音符を表し、3 は八分音符を表す、等々。パラメータ cc は、1 メトロノーム・ - * クリックあたりの MIDI クロック数を表現している。パラメータ bb は、 MIDI - * 四分音符(24 MIDI クロック)の中に記譜上の三十二分音符がいくつ入るかを - * 表現している。このパラメータは、 MIDI 上の四分音符(24 クロック)を他 - * のものとして記譜し、あるいは表現上他の音符に対応させるようユーザ定義で - * きるプログラムが既に数多く存在することから加えられた。 - * - * 従って、6 / 8 拍子で、メトロノームは八分音符 3 つ毎に刻むけれども四分音 - * 符 24 クロックで、1 小節あたりでは 72 クロックになる拍子は、16 進で次 - * のようになる。 - * - * FF 58 04 06 03 24 08 - * - * これは、8 分の 6 拍子で(8 は 2 の 3 乗なので、06 03となる)、付点四分音 - * 符あたり 36 MIDI クロック(16進で24!)[*2]で、 MIDI 四分音符に記 - * 譜上の三十二分音符が 8 つ対応するということを示している。 - */ - public static final int META_58 = 0x58; // 88 - - /** - *
    -     * FF 59 02 sf mi  [調号]
    -     *   sf = -7  フラット7つ
    -     *   sf = -1  フラット1つ
    -     *   sf = 0   ハ調
    -     *   sf = 1   シャープ1つ
    -     *   sf = 7   シャープ7つ
    -     *
    -     *   mi = 0   長調
    -     *   mi = 1   短調
    -     * 
    - */ - public static final int META_59 = 0x59; // 89 - - /** - *
    -     * FF 7F len data  [シーケンサー特定メタ・イベント]
    -     * 
    - * 特定のシーケンサーのための特別な要求にこのイベント・タイプを用いること - * ができる。データ・バイトの最初の1バイトはメーカーIDである。しかしな - * がら、これは交換用フォーマットなのであるから、このイベント・タイプの使 - * 用よりもスペック本体の拡張の方が望ましい。このタイプのイベントは、これ - * を唯一のファイル・フォーマットとして用いることを選択したシーケンサーに - * よって使用されるかもしれない。仕様詳細のフォーマットが確定したシーケン - * サーにおいては、このフォーマットを用いるにあたって標準仕様を守るべきで - * あろう。 - */ - public static final int META_MACHINE_DEPEND = 0x7f; // 127 + public enum MetaEvent { + /** + *
    +         * FF 00 02 ssss  [シーケンス・ナンバー]
    +         * 
    + * このオプション・イベントは、トラックの冒頭、任意の 0 でないデルタ・タイ + * ムの前で、かつ任意の転送可能な MIDI イベントの前に置かれなければならず + * 、これがシーケンスのナンバーを特定する。このトラック中のナンバーは + * 1987 年夏の MMA ミーティングで協議された新 Cue メッセージの中のシーケンス + * ・ナンバーに対応する。これは、フォーマット 2 の MIDI ファイルにおいては + * 、各々の「パターン」を識別することによって、Cue メッセージを用いている + * 「ソング」シーケンスがパターンを参照できるようにするために用いられる。 + * ID ナンバーが省略されているときは、そのシーケンスのファイル中での位置 + * [訳注:先頭から何番目のシーケンスか]がデフォールトとして用いられる。 + * フォーマット 0 または 1 の MIDI ファイルにおいては、1つのシーケンスしか + * 含まれないため、このナンバーは第 1 の(つまり唯一の)トラックに含まれ + * ることになる。いくつかのマルチトラック・シーケンスの転送が必要な場合は + * 、各々が異なるシーケンス・ナンバーを持つフォーマット1のファイルのグル + * ープとして行われなければならない。 + */ + META_SEQUENCE_NO(0x00), + + /** + *
    +         * FF 01 len text  [テキスト・イベント]
    +         * 
    + * 任意の大きさおよび内容のテキスト。トラックのいちばん初めに、トラック名 + * 、意図するオーケストレイション、その他ユーザがそこに置きたいと思う情報 + * を書いておくと良い。テキスト・イベントは、トラック中でその他の時に入れ + * て歌詞やキュー・ポイントの記述として用いることもできる。このイベント中 + * のテキストは、最大限の互換性を確保するために、印刷可能なアスキー・キャ + * ラクタでなければならない。しかし、高位ビットを用いる他のキャラクタ・コ + * ード(訳注:漢字コードのような 2 バイト・コードなど)も、拡張されたキャ + * ラクタ・セットをサポートする同じコンピュータ上の異なるプログラム間でフ + * ァイルを交換するために用いることができる。非アスキー・キャラクタをサポ + * ートしない機種上のプログラムは、このようなコードを無視しなければならな + * い。 + * + * (0.06 での追加事項) メタ・イベントのタイプ 01 から 0F までは様々なタ + * イプのテキスト・イベントのために予約されている。この各々は上記のテキス + * ト・イベントの特性と重複しているが、以下のように、異なる目的のために用 + * いられる。 + */ + META_TEXT_EVENT(0x01), + + /** + *
    +         * FF 02 len text  [著作権表示]
    +         * 
    + * 著作権表示を、印刷可能なアスキー・テキストとして持つ。この表示には(C) + * の文字と、著作物発行年と、著作権所有者名とが含まれなければならない。ひ + * とつの MIDI ファイルに幾つかの楽曲がある時には、すべての著作権表示をこ + * のイベントに置いて、それがファイルの先頭に来るようにしなければならない + * 。このイベントは第1トラック・ブロックの最初のイベントとして、デルタ・ + * タイム = 0 で置かれなければならない。 + */ + META_COPYRIGHT(0x02), + + /** + *
    +         * FF 03 len text  [シーケンス名またはトラック名]
    +         * 
    + * フォーマット 0 のトラック、もしくはフォーマット 1 のファイルの第 1 トラッ + * クにおいては、シーケンスの名称。その他の場合は、トラックの名称。 + */ + META_NAME(0x03), + + /** + *
    +         * FF 04 len text  [楽器名]
    +         * 
    + * そのトラックで用いられるべき楽器編成の種類を記述する。 MIDI の冒頭に置 + * かれるメタ・イベントとともに用いて、どの MIDI チャネルにその記述が適用 + * されるかを特定することもある。あるいは、チャネルをこのイベント中のテキ + * ストで特定しても良い。 + */ + META_INSTRUMENT(0x04), + + /** + *
    +         * FF 05 len text  [歌詞]
    +         * 
    + * 歌詞。一般的には、各音節がそのイベントのタイムから始まる独立した歌詞イ + * ベントとなる。 + */ + META_LYRICS(0x05), + + /** + *
    +         * FF 06 len text  [マーカー]
    +         * 
    + * 通常フォーマット 0 のトラック、もしくはフォーマット 1 のファイルの第1ト + * ラックにある。リハーサル記号やセクション名のような、シーケンスのその時 + * 点の名称。(「First Verse」等) + */ + META_MARKER(0x06), + + /** + *
    +         * FF 07 len text  [キュー・ポイント]
    +         * 
    + * スコアのその位置において、フィルム、ヴィデオ・スクリーン、あるいはステ + * ージ上で起こっていることの記述。(「車が家に突っ込む」「幕が開く」「女 + * は男に平手打ちを食わせる」等) + */ + META_QUE_POINT(0x07), + + /** + *
    +         * FF 2F 00  [トラックの終わり]
    +         * 
    + * このイベントは省略することができない。これがあることによってトラックの + * 正しい終結点が明確になり、トラックが正確な長さを持つようになる。これは + * トラックがループになっていたり連結されていたりする時に必要である。 + */ + META_END_OF_TRACK(0x2f), // 47 + + /** + *
    +         * FF 51 03 tttttt  [テンポ設定(単位は μsec / MIDI 四分音符)]
    +         * 
    + * このイベントはテンポ・チェンジを指示する。「μsec / MIDI 四分音符」は + * 言い換えれば「(μsec / MIDI クロック)の 24 分の 1」である。テンポを + * 「拍 / 時間」ではなく「時間 / 拍」によって与えることで、 SMPTE タイム・ + * コードや MIDI タイム・コードのような実時間ベースの同期プロトコルを用い + * て、絶対的に正確な長時間同期を得ることができる。このテンポ設定で得られ + * る正確さは、120 拍 / 分で 4 分の曲を終わった時に誤差が 500 μsec 以内 + * にとどまる、というものである。理想的には、これらのイベントは Cue の + * 上で MIDI クロックがある位置にのみ、おかれるべきである。このことは、ほか + * の同期デバイスとの互換性を保証しよう、少なくとも、その見込みを増やそう + * 、というもので、この結果、この形式で保存された拍子記号やテンポ・マップ + * は容易にほかのデバイスへ転送できることになる。 + */ + META_TEMPO(0x51), // 81 + + /** + *
    +         * FF 54 05 hr mn se fr ff  [SMPTE オフセット(0.06 での追加 - SMPTE フォーマットの記述)]
    +         * 
    + * このイベントは、もしあれば、トラック・ブロックがスタートすることになっ + * ている SMPTE タイムを示す。これは、トラックの冒頭に置かれなければなら + * ない。すなわち、任意の 0 でないデルタ・タイムの前で、かつ任意の転送可能 + * な MIDI イベントの前である。時間は、 MIDI タイム・コードと全く同様に + * SMPTE フォーマットでエンコードされなければならない。フォーマット 1 のフ + * ァイルにおいては、 SMPTE オフセットはテンポ・マップとともにストアされ + * る必要があり、他のトラックにあっては意味をなさない。デルタ・タイムのた + * めに異なるフレーム分解能を指定している SMPTE ベースのトラックにおいて + * も、ff のフィールドは細分化されたフレーム(100 分の 1 フレーム単位)を + * 持っている。 + */ + META_SMPTE_OFFSERT(0x54), // 84 + + /** + *
    +         * FF 58 04 nn dd cc bb  [拍子記号]
    +         * 
    + * 拍子記号は、4 つの数字で表現される。nn と dd は、記譜する時のように、拍子 + * 記号の分子と分母を表す。分母は 2 のマイナス乗である。すなわち、2 は四分 + * 音符を表し、3 は八分音符を表す、等々。パラメータ cc は、1 メトロノーム・ + * クリックあたりの MIDI クロック数を表現している。パラメータ bb は、 MIDI + * 四分音符(24 MIDI クロック)の中に記譜上の三十二分音符がいくつ入るかを + * 表現している。このパラメータは、 MIDI 上の四分音符(24 クロック)を他 + * のものとして記譜し、あるいは表現上他の音符に対応させるようユーザ定義で + * きるプログラムが既に数多く存在することから加えられた。 + * + * 従って、6 / 8 拍子で、メトロノームは八分音符 3 つ毎に刻むけれども四分音 + * 符 24 クロックで、1 小節あたりでは 72 クロックになる拍子は、16 進で次 + * のようになる。 + * + * FF 58 04 06 03 24 08 + * + * これは、8 分の 6 拍子で(8 は 2 の 3 乗なので、06 03となる)、付点四分音 + * 符あたり 36 MIDI クロック(16進で24!)[*2]で、 MIDI 四分音符に記 + * 譜上の三十二分音符が 8 つ対応するということを示している。 + */ + META_58(0x58), // 88 + + /** + *
    +         * FF 59 02 sf mi  [調号]
    +         *   sf = -7  フラット7つ
    +         *   sf = -1  フラット1つ
    +         *   sf = 0   ハ調
    +         *   sf = 1   シャープ1つ
    +         *   sf = 7   シャープ7つ
    +         *
    +         *   mi = 0   長調
    +         *   mi = 1   短調
    +         * 
    + */ + META_59(0x59), // 89 + + /** + *
    +         * FF 7F len data  [シーケンサー特定メタ・イベント]
    +         * 
    + * 特定のシーケンサーのための特別な要求にこのイベント・タイプを用いること + * ができる。データ・バイトの最初の1バイトはメーカーIDである。しかしな + * がら、これは交換用フォーマットなのであるから、このイベント・タイプの使 + * 用よりもスペック本体の拡張の方が望ましい。このタイプのイベントは、これ + * を唯一のファイル・フォーマットとして用いることを選択したシーケンサーに + * よって使用されるかもしれない。仕様詳細のフォーマットが確定したシーケン + * サーにおいては、このフォーマットを用いるにあたって標準仕様を守るべきで + * あろう。 + */ + META_MACHINE_DEPEND(0x7f), // 127 + META_UNDEFINED(-1); + int number; + public int number() { + return number; + } + MetaEvent(int number) { + this.number = number; + } + public static MetaEvent valueOf(int number) { + try { + return Arrays.stream(values()).filter(e -> e.number == number).findFirst().get(); + } catch (NoSuchElementException e) { + META_UNDEFINED.number = number; // TODO evil and not thread safe. +Debug.println(Level.WARNING, "undefined meta: " + number); + return META_UNDEFINED; + } + } + @Override + public String toString() { + if (ordinal() == META_UNDEFINED.ordinal()) { + return super.toString() + " (" + number + ")"; + } else { + return super.toString(); + } + } + } //------------------------------------------------------------------------- diff --git a/src/main/java/vavi/sound/midi/MidiUtil.java b/src/main/java/vavi/sound/midi/MidiUtil.java index c376ee2..c4f869d 100644 --- a/src/main/java/vavi/sound/midi/MidiUtil.java +++ b/src/main/java/vavi/sound/midi/MidiUtil.java @@ -14,9 +14,11 @@ import java.util.ServiceLoader; import java.util.logging.Level; +import javax.sound.midi.InvalidMidiDataException; import javax.sound.midi.MetaMessage; import javax.sound.midi.MidiDevice; import javax.sound.midi.MidiMessage; +import javax.sound.midi.Receiver; import javax.sound.midi.Sequencer; import javax.sound.midi.ShortMessage; import javax.sound.midi.Synthesizer; @@ -38,6 +40,16 @@ public final class MidiUtil { private MidiUtil() { } + /** + * @param volume 0 ~ 1.0 + */ + public static void volume(Receiver receiver, float volume) throws InvalidMidiDataException { + int value = (int) (16383 * volume); + byte[] data = { (byte) 0xf0, 0x7f, 0x7f, 0x04, 0x01, (byte) (value & 0x7f), (byte) ((value >> 7) & 0x7f), (byte) 0xf7 }; + MidiMessage sysex = new SysexMessage(data, data.length); + receiver.send(sysex, -1); + } + /** */ public static String paramString(MidiMessage midiMessage) { String result = null; @@ -107,7 +119,10 @@ private static String getChannelMessage(int statusByte, int value1) { } } - /** */ + /** + * read 1 ~ 4 bytes + * @return 0 ~ 268435455 (0x0fffffff) + */ public static int readVariableLength(DataInput input) throws IOException { int b = input.readUnsignedByte(); int v = b & 0x7f; diff --git a/src/main/java/vavi/sound/midi/mfi/MfiMidiFileReader.java b/src/main/java/vavi/sound/midi/mfi/MfiMidiFileReader.java index f9355db..1ba7e57 100644 --- a/src/main/java/vavi/sound/midi/mfi/MfiMidiFileReader.java +++ b/src/main/java/vavi/sound/midi/mfi/MfiMidiFileReader.java @@ -6,8 +6,10 @@ package vavi.sound.midi.mfi; +import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.Arrays; import java.util.logging.Level; import javax.sound.midi.InvalidMidiDataException; @@ -21,36 +23,57 @@ /** - * MfiMidiFileReader implemented by vavi. + * MfiMidiFileReader implemented by vavi.sound.mfi.vavi package * * @author Naohide Sano (nsano) * @version 0.00 030817 nsano initial version
    */ public class MfiMidiFileReader extends BasicMidiFileReader { - /** MFi から変換された MIDI Sequence を取得します。 */ + /** Gets a MIDI Sequence converted from MFi */ public Sequence getSequence(InputStream is) throws InvalidMidiDataException, IOException { + boolean reset = false; + try { if (!is.markSupported()) { + // TODO should be wrap by BufferedInputStream? throw new IOException("mark not supported: " + is); } - is.mark(4); // 4 は MfiSystem#getSequence が 4 bytes で判断できることに依存している + is.mark(4); // 4 means MfiSystem#getSequence is able to determine it 4 bytes + + DataInputStream dis = new DataInputStream(is); + byte[] b = new byte[4]; + dis.readFully(b); + if (!Arrays.equals(b, "melo".getBytes())) { + throw new InvalidMidiDataException("not MFi signature"); + } else { + is.reset(); + reset = true; + } vavi.sound.mfi.Sequence mfiSequence = MfiSystem.getSequence(is); //Debug.println(mfiSequence); return MfiSystem.toMidiSequence(mfiSequence); } catch (InvalidMfiDataException e) { - is.reset(); Debug.println(Level.FINE, e); //Debug.printStackTrace(e); throw (InvalidMidiDataException) new InvalidMidiDataException().initCause(e); } catch (MfiUnavailableException e) { Debug.println(Level.SEVERE, e); - throw (IOException) new IOException().initCause(e); + throw new IOException(e); + } finally { + try { + if (!reset) { + is.reset(); + } + } catch (IOException e) { +Debug.println(Level.SEVERE, e); + throw e; + } } } } diff --git a/src/main/java/vavi/sound/midi/mfi/package.html b/src/main/java/vavi/sound/midi/mfi/package.html deleted file mode 100644 index eab84d2..0000000 --- a/src/main/java/vavi/sound/midi/mfi/package.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - -vavi.sound.midi.mfi - - - - - -

    -MIDI のサービスプロバイダ実装例 (MFi) のクラスを提供します。 -

    - -
      -
    • fileType は 0x88
    • -
    - -

    これから実装すること

    - -
      -
    • midi spi のとき MetaEvent 06 がリッスンされていない → MetaListener - の提供
    • -
    • MetaEventApapter を Sequencer にあらかじめ付けておく
    • -
    • spi に追加した場合 SMF もストリームから読めなくなる
    • -
    - - - - diff --git a/src/main/java/vavi/sound/midi/mfi/readme.md b/src/main/java/vavi/sound/midi/mfi/readme.md new file mode 100644 index 0000000..cd980ae --- /dev/null +++ b/src/main/java/vavi/sound/midi/mfi/readme.md @@ -0,0 +1,11 @@ +# vavi.sound.midi.mfi + +MIDI のサービスプロバイダ実装例 (MFi) のクラスを提供します。 + +fileType は 0x88 + +# TODO + + * ~~midi spi のとき MetaEvent 06 がリッスンされていない → MetaListener の提供~~ + * MetaEventApapter を Sequencer にあらかじめ付けておく~~ + * ~~spi に追加した場合 SMF もストリームから読めなくなる~~ diff --git a/src/main/java/vavi/sound/midi/smaf/SmafMidiFileReader.java b/src/main/java/vavi/sound/midi/smaf/SmafMidiFileReader.java index 0cd2753..499d6a7 100644 --- a/src/main/java/vavi/sound/midi/smaf/SmafMidiFileReader.java +++ b/src/main/java/vavi/sound/midi/smaf/SmafMidiFileReader.java @@ -6,8 +6,10 @@ package vavi.sound.midi.smaf; +import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.Arrays; import java.util.logging.Level; import javax.sound.midi.InvalidMidiDataException; @@ -21,7 +23,7 @@ /** - * SmafMidiFileReader implemented by vavi. + * SmafMidiFileReader implemented by vavi.sound.smaf package * * @author Naohide Sano (nsano) * @version 0.00 041222 nsano initial version
    @@ -33,24 +35,45 @@ public Sequence getSequence(InputStream is) throws InvalidMidiDataException, IOException { + boolean reset = false; + try { if (!is.markSupported()) { + // TODO should be wrap by BufferedInputStream? throw new IOException("mark not supported: " + is); } - is.mark(4); // 4 は SmafSystem#getSequence が 4 bytes で判断できることに依存している + is.mark(4); // 4 means SmafSystem#getSequence is able to determine it by 4 bytes + + DataInputStream dis = new DataInputStream(is); + byte[] b = new byte[4]; + dis.readFully(b); + if (!Arrays.equals(b, "MMMD".getBytes())) { + throw new InvalidMidiDataException("not SMAF signature"); + } else { + is.reset(); + reset = true; + } vavi.sound.smaf.Sequence sequence = SmafSystem.getSequence(is); //Debug.println(sequence); return SmafSystem.toMidiSequence(sequence); } catch (InvalidSmafDataException e) { - is.reset(); -Debug.println(Level.FINE, e); +Debug.println(Level.INFO, e); //Debug.printStackTrace(e); throw (InvalidMidiDataException) new InvalidMidiDataException().initCause(e); } catch (SmafUnavailableException e) { Debug.println(Level.SEVERE, e); - throw (IOException) new IOException().initCause(e); + throw new IOException(e); + } finally { + try { + if (!reset) { + is.reset(); + } + } catch (IOException e) { +Debug.println(Level.SEVERE, e); + throw e; + } } } } diff --git a/src/main/java/vavi/sound/midi/smaf/package.html b/src/main/java/vavi/sound/midi/smaf/package.html deleted file mode 100644 index 36ecab9..0000000 --- a/src/main/java/vavi/sound/midi/smaf/package.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - -vavi.sound.midi.smaf - - - - - -

    -MIDI のサービスプロバイダ実装例 (SMAF) のクラスを提供します。 -

    - -
      -
    • fileType は 0x84 (MobileStandard)
    • -
    - -

    これから実装すること

    - -
      -
    • Handyphone とか Compress とか
    • -
    - - - - diff --git a/src/main/java/vavi/sound/midi/smaf/readme.md b/src/main/java/vavi/sound/midi/smaf/readme.md new file mode 100644 index 0000000..47b9e7e --- /dev/null +++ b/src/main/java/vavi/sound/midi/smaf/readme.md @@ -0,0 +1,9 @@ +# vavi.sound.midi.smaf + +MIDI のサービスプロバイダ実装例 (SMAF) のクラスを提供します。 + +fileType は 0x84 (MobileStandard) + +## TODO + + * Handyphone とか Compress とか diff --git a/src/main/java/vavi/sound/mobile/AudioEngine.java b/src/main/java/vavi/sound/mobile/AudioEngine.java index 22fd31f..d8ec01f 100644 --- a/src/main/java/vavi/sound/mobile/AudioEngine.java +++ b/src/main/java/vavi/sound/mobile/AudioEngine.java @@ -12,10 +12,12 @@ /** * AudioEngine. *

    - * {@link vavi.sound.mfi.vavi.sequencer.AudioDataSequencer} で使用されます。 - * 条件は引数なしのコンストラクタがあること、 - * {@link #encode(int, int, byte[])} に関連する部分は - * ステートレスでなければならないことです。 + * Used in {@link vavi.sound.mfi.vavi.sequencer.AudioDataSequencer}. + *

    + *

    + * Currently, an implementation class of this interface should be an bean. + * (means having a contractor without argument) + * {@link #encode(int, int, byte[])} related should be stateless. *

    * @author Naohide Sano (nsano) * @version 0.00 051116 nsano initial version
    @@ -77,15 +79,15 @@ class Data { public boolean continued = false; } - /** */ + /** monaural stereo conversion */ class Util { - /** */ + /** left */ private static final int L = 0; - /** */ + /** right */ private static final int R = 1; /** - * インターリーブされた PCM を L R 順に分離 + * separates interleaved PCM to an array L R order. * @param stereo PCM stereo, currently 16bit only * @param bits PCM bits, TODO currently unused * @param byteOrder PCM 16 bit byte order, TODO currently unused @@ -116,7 +118,7 @@ public static byte[][] toMono(byte[] stereo, int bits, ByteOrder byteOrder) { } /** - * インターリーブするというらしい。 + * this seems to say interleave. * @param monoL ADPCM monaural L, currently 4bit only * @param monoR ADPCM monaural R, currently 4bit only * @param bits ADPCM bits, TODO currently unused @@ -137,7 +139,7 @@ public static byte[] toStereo(byte[] monoL, byte[] monoR, int bits, ByteOrder by } /** - * インターリーブしない。 + * not interleaved. * @param monoL adpcm data L * @param monoR adpcm data R * @return L, R concatenated adpcm data diff --git a/src/main/java/vavi/sound/mobile/BasicAudioEngine.java b/src/main/java/vavi/sound/mobile/BasicAudioEngine.java index 2a948fb..bfddc6b 100644 --- a/src/main/java/vavi/sound/mobile/BasicAudioEngine.java +++ b/src/main/java/vavi/sound/mobile/BasicAudioEngine.java @@ -16,12 +16,13 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; import vavi.util.Debug; +import static vavi.sound.SoundUtil.volume; + /** * Abstract AudioEngine. @@ -34,7 +35,7 @@ public abstract class BasicAudioEngine implements AudioEngine { /** */ protected Data[] data; - /* */ + @Override public void setData(int streamNumber, int channel, int sampleRate, @@ -64,7 +65,7 @@ public void setData(int streamNumber, // debug1(); } - /** */ + @Override public void stop(int streamNumber) { } @@ -74,7 +75,7 @@ public void stop(int streamNumber) { /** */ protected abstract InputStream[] getInputStreams(int streamNumber, int channels); - /** */ + @Override public void start(int streamNumber) { int channels = getChannels(streamNumber); @@ -105,10 +106,7 @@ public void start(int streamNumber) { SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info); line.open(audioFormat); line.start(); -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); byte[] buf = new byte[1024]; while (iss[0].available() > 0) { if (channels == 1) { @@ -146,7 +144,7 @@ public void start(int streamNumber) { /** */ protected abstract OutputStream getOutputStream(OutputStream os); - /* */ + @Override public byte[] encode(int bits, int channels, byte[] pcm) { try { if (channels == 1) { diff --git a/src/main/java/vavi/sound/mobile/FuetrekAudioEngine.java b/src/main/java/vavi/sound/mobile/FuetrekAudioEngine.java index 119d63b..cae3c17 100644 --- a/src/main/java/vavi/sound/mobile/FuetrekAudioEngine.java +++ b/src/main/java/vavi/sound/mobile/FuetrekAudioEngine.java @@ -42,7 +42,7 @@ public FuetrekAudioEngine() { data = new Data[MAX_ID]; } - /** */ + @Override protected int getChannels(int streamNumber) { int channels = 1; if (data[streamNumber].channel != -1) { @@ -64,7 +64,7 @@ protected int getChannels(int streamNumber) { return channels; } - /** */ + @Override protected InputStream[] getInputStreams(int streamNumber, int channels) { InputStream[] iss = new InputStream[2]; if (data[streamNumber].channels == 1) { @@ -101,7 +101,7 @@ protected InputStream[] getInputStreams(int streamNumber, int channels) { //------------------------------------------------------------------------- - /** */ + @Override protected OutputStream getOutputStream(OutputStream os) { return new G721OutputStream(os, ByteOrder.LITTLE_ENDIAN); } diff --git a/src/main/java/vavi/sound/mobile/PcmAudioEngine.java b/src/main/java/vavi/sound/mobile/PcmAudioEngine.java index 676e8d3..73592f2 100644 --- a/src/main/java/vavi/sound/mobile/PcmAudioEngine.java +++ b/src/main/java/vavi/sound/mobile/PcmAudioEngine.java @@ -14,27 +14,29 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; import vavi.util.Debug; +import static vavi.sound.SoundUtil.volume; + /** * PCM AudioEngine. - * -WSC-MAX_DLL -DLL - Input File Output File -wscma2_dll File Format Bit Sampling Frequency Form Conversion Format File Format -wscma3_dll WAVE 16bit 4kHz or 8kHz mono 4bit ADPCM SMAF/MA-2 - WAVE 16bit 4kHz~16kHz mono 4bit ADPCM SMAF/MA-3 -wscma5_dll WAVE 16bit or 8bit 4kHz~ 8kHz mono 8bit PCM SMAF/MA-3 - WAVE or AIFF 16bit 4kHz~24kHz mono 4bit ADPCM SMAF/MA-5 - WAVE or AIFF 16bit or 8bit 4kHz~12kHz mono 8bit PCM SMAF/MA-5 - WAVE or AIFF 16bit 4kHz~12kHz stereo 4bit ADPCM SMAF/MA-5 - WAVE or AIFF 16bit or 8bit 4kHz~6kHz stereo 8bit PCM SMAF/MA-5 + *
    + * WSC-MAX_DLL
    + * DLL
    + *                  Input File                                                               Output File
    + * wscma2_dll       File Format         Bit              Sampling Frequency      Form        Conversion Format   File Format
    + * wscma3_dll       WAVE                16bit            4kHz or 8kHz            mono        4bit ADPCM          SMAF/MA-2
    + *                  WAVE                16bit            4kHz~16kHz              mono        4bit ADPCM          SMAF/MA-3
    + * wscma5_dll       WAVE                16bit or 8bit    4kHz~ 8kHz              mono        8bit PCM            SMAF/MA-3
    + *                  WAVE or AIFF        16bit            4kHz~24kHz              mono        4bit ADPCM          SMAF/MA-5
    + *                  WAVE or AIFF        16bit or 8bit    4kHz~12kHz              mono        8bit PCM            SMAF/MA-5
    + *                  WAVE or AIFF        16bit            4kHz~12kHz             stereo       4bit ADPCM          SMAF/MA-5
    + *                  WAVE or AIFF        16bit or 8bit    4kHz~6kHz              stereo       8bit PCM            SMAF/MA-5
    + * 
    * * @author Naohide Sano (nsano) * @version 0.00 020829 nsano initial version
    @@ -52,7 +54,7 @@ public PcmAudioEngine() { data = new Data[32]; } - /** */ + @Override protected int getChannels(int streamNumber) { int channels = 1; if (data[streamNumber].channel == -1) { @@ -84,7 +86,7 @@ protected int getChannels(int streamNumber) { return channels; } - /** */ + @Override protected InputStream[] getInputStreams(int streamNumber, int channels) { InputStream[] iss = new InputStream[2]; if (data[streamNumber].channels == 1) { @@ -105,11 +107,12 @@ protected InputStream[] getInputStreams(int streamNumber, int channels) { //------------------------------------------------------------------------- - /** */ + @Override protected OutputStream getOutputStream(OutputStream os) { return os; } + @Override public void start(int streamNumber) { int channels = getChannels(streamNumber); @@ -140,10 +143,7 @@ public void start(int streamNumber) { SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info); line.open(audioFormat); line.start(); -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); byte[] buf = new byte[1024]; while (iss[0].available() > 0) { if (channels == 1) { @@ -169,9 +169,7 @@ public void start(int streamNumber) { line.stop(); line.close(); // debug4(os); - } catch (IOException e) { - throw new IllegalStateException(e); - } catch (LineUnavailableException e) { + } catch (IOException | LineUnavailableException e) { throw new IllegalStateException(e); } } diff --git a/src/main/java/vavi/sound/mobile/RohmAudioEngine.java b/src/main/java/vavi/sound/mobile/RohmAudioEngine.java index da66309..2c47390 100644 --- a/src/main/java/vavi/sound/mobile/RohmAudioEngine.java +++ b/src/main/java/vavi/sound/mobile/RohmAudioEngine.java @@ -40,7 +40,7 @@ public RohmAudioEngine() { data = new Data[MAX_ID]; } - /** */ + @Override protected int getChannels(int streamNumber) { int channels = 1; if (data[streamNumber].channel != -1) { @@ -61,7 +61,7 @@ protected int getChannels(int streamNumber) { return channels; } - /** */ + @Override protected InputStream[] getInputStreams(int streamNumber, int channels) { InputStream[] iss = new InputStream[2]; if (data[streamNumber].channels == 1) { @@ -82,7 +82,7 @@ protected InputStream[] getInputStreams(int streamNumber, int channels) { //------------------------------------------------------------------------- - /** */ + @Override protected OutputStream getOutputStream(OutputStream os) { return new RohmOutputStream(os, ByteOrder.LITTLE_ENDIAN); } diff --git a/src/main/java/vavi/sound/mobile/YamahaAudioEngine.java b/src/main/java/vavi/sound/mobile/YamahaAudioEngine.java index 63fc34d..e0ffcc1 100644 --- a/src/main/java/vavi/sound/mobile/YamahaAudioEngine.java +++ b/src/main/java/vavi/sound/mobile/YamahaAudioEngine.java @@ -34,7 +34,7 @@ public YamahaAudioEngine() { data = new Data[32]; } - /** */ + @Override protected int getChannels(int streamNumber) { int channels = 1; if (data[streamNumber].channel == -1) { @@ -66,7 +66,7 @@ protected int getChannels(int streamNumber) { return channels; } - /** */ + @Override protected InputStream[] getInputStreams(int streamNumber, int channels) { InputStream[] iss = new InputStream[2]; if (data[streamNumber].channels == 1) { @@ -87,7 +87,7 @@ protected InputStream[] getInputStreams(int streamNumber, int channels) { //------------------------------------------------------------------------- - /** */ + @Override protected OutputStream getOutputStream(OutputStream os) { return new MaOutputStream(os, ByteOrder.LITTLE_ENDIAN); } diff --git a/src/main/java/vavi/sound/mobile/package.html b/src/main/java/vavi/sound/mobile/package.html deleted file mode 100644 index e469e09..0000000 --- a/src/main/java/vavi/sound/mobile/package.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - -vavi.sound.mobile - - - - - -

    -mobile 用の wave シーケンサのクラスを提供します。 -

    - -

    これから実装すること

    - -
      -
    • continued がおかしい
    • -
    - - - - diff --git a/src/main/java/vavi/sound/mobile/readme.md b/src/main/java/vavi/sound/mobile/readme.md new file mode 100644 index 0000000..985dd71 --- /dev/null +++ b/src/main/java/vavi/sound/mobile/readme.md @@ -0,0 +1,7 @@ +# vavi.sound.mobile + +mobile 用の wave シーケンサのクラスを提供します。 + +## TODO + + * continued がおかしい diff --git a/src/main/java/vavi/sound/package.html b/src/main/java/vavi/sound/package.html deleted file mode 100644 index cb3772b..0000000 --- a/src/main/java/vavi/sound/package.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - -vavi.sound - - - - - -

    -サウンド関連のクラスを提供します. -

    - - - - diff --git a/src/main/java/vavi/sound/pcm/resampling/ssrc/SSRC.java b/src/main/java/vavi/sound/pcm/resampling/ssrc/SSRC.java index 1cbd35a..45a4cc9 100644 --- a/src/main/java/vavi/sound/pcm/resampling/ssrc/SSRC.java +++ b/src/main/java/vavi/sound/pcm/resampling/ssrc/SSRC.java @@ -1896,11 +1896,11 @@ public void exec(String[] argv) throws IOException { fo = new File(dfn); try (FileInputStream fis = new FileInputStream(sfn); - FileOutputStream fos = new FileOutputStream(fo)) { + FileOutputStream fos = new FileOutputStream(fo)) { - FileChannel fpi = fis.getChannel(); + FileChannel fpi = fis.getChannel(); - // read wav header + // read wav header short word; int dword; @@ -1975,63 +1975,63 @@ public void exec(String[] argv) throws IOException { throw new IllegalStateException("Couldn't find data chank"); } - if (bps != 1 && bps != 2 && bps != 3 && bps != 4) { - throw new IllegalStateException("Error : Only 8bit, 16bit, 24bit and 32bit PCM are supported."); - } - - if (dbps == -1) { - if (bps != 1) { - dbps = bps; - } else { - dbps = 2; - } - if (dbps == 4) { - dbps = 3; - } - } - - if (dfrq == -1) { - dfrq = sfrq; - } - - if (dither == -1) { - if (dbps < bps) { - if (dbps == 1) { - dither = 4; - } else { - dither = 3; - } - } else { - dither = 1; - } - } - - if (!quiet) { - final String[] dtype = { - "none", "no noise shaping", "triangular spectral shape", "ATH based noise shaping", "ATH based noise shaping(less amplitude)" - }; - final String[] ptype = { - "rectangular", "triangular", "gaussian" - }; - System.err.printf("frequency : %d -> %d\n", sfrq, dfrq); - System.err.printf("attenuation : %gdB\n", att); - System.err.printf("bits per sample : %d -> %d\n", bps * 8, dbps * 8); - System.err.printf("nchannels : %d\n", nch); - System.err.printf("length : %d bytes, %g secs\n", length, (double) length / bps / nch / sfrq); - if (dither == 0) { - System.err.printf("dither type : none\n"); - } else { - System.err.printf("dither type : %s, %s p.d.f, amp = %g\n", dtype[dither], ptype[pdf], noiseamp); - } - System.err.printf("\n"); - } - - if (twopass) { - } - - fpo = fos.getChannel(); - - // generate wav header + if (bps != 1 && bps != 2 && bps != 3 && bps != 4) { + throw new IllegalStateException("Error : Only 8bit, 16bit, 24bit and 32bit PCM are supported."); + } + + if (dbps == -1) { + if (bps != 1) { + dbps = bps; + } else { + dbps = 2; + } + if (dbps == 4) { + dbps = 3; + } + } + + if (dfrq == -1) { + dfrq = sfrq; + } + + if (dither == -1) { + if (dbps < bps) { + if (dbps == 1) { + dither = 4; + } else { + dither = 3; + } + } else { + dither = 1; + } + } + + if (!quiet) { + final String[] dtype = { + "none", "no noise shaping", "triangular spectral shape", "ATH based noise shaping", "ATH based noise shaping(less amplitude)" + }; + final String[] ptype = { + "rectangular", "triangular", "gaussian" + }; + System.err.printf("frequency : %d -> %d\n", sfrq, dfrq); + System.err.printf("attenuation : %gdB\n", att); + System.err.printf("bits per sample : %d -> %d\n", bps * 8, dbps * 8); + System.err.printf("nchannels : %d\n", nch); + System.err.printf("length : %d bytes, %g secs\n", length, (double) length / bps / nch / sfrq); + if (dither == 0) { + System.err.printf("dither type : none\n"); + } else { + System.err.printf("dither type : %s, %s p.d.f, amp = %g\n", dtype[dither], ptype[pdf], noiseamp); + } + System.err.printf("\n"); + } + + if (twopass) { + } + + fpo = fos.getChannel(); + + // generate wav header ByteBuffer leos = ByteBuffer.allocate(44).order(ByteOrder.LITTLE_ENDIAN); @@ -2062,216 +2062,216 @@ public void exec(String[] argv) throws IOException { leos.flip(); fpo.write(leos); - if (dither != 0) { - int min = 0, max = 0; - if (dbps == 1) { - min = -0x80; - max = 0x7f; - } - if (dbps == 2) { - min = -0x8000; - max = 0x7fff; - } - if (dbps == 3) { - min = -0x800000; - max = 0x7fffff; - } - if (dbps == 4) { - min = -0x80000000; - max = 0x7fffffff; - } - - samp = init_shaper(dfrq, nch, min, max, dither, pdf, noiseamp); - } - - if (twopass) { - double gain = 0; - int ch = 0; - int fptlen, sumread; - - if (!quiet) { - System.err.printf("Pass 1\n"); - } - - if (tmpfn != null) { - ft = new File(tmpfn); - } else { - ft = File.createTempFile("ssrc_", ".tmp"); - } - try (FileOutputStream tfos= new FileOutputStream(ft)) { - fpto = tfos.getChannel(); - + if (dither != 0) { + int min = 0, max = 0; + if (dbps == 1) { + min = -0x80; + max = 0x7f; + } + if (dbps == 2) { + min = -0x8000; + max = 0x7fff; + } + if (dbps == 3) { + min = -0x800000; + max = 0x7fffff; + } + if (dbps == 4) { + min = -0x80000000; + max = 0x7fffffff; + } + + samp = init_shaper(dfrq, nch, min, max, dither, pdf, noiseamp); + } + + if (twopass) { + double gain = 0; + int ch = 0; + int fptlen, sumread; + + if (!quiet) { + System.err.printf("Pass 1\n"); + } + + if (tmpfn != null) { + ft = new File(tmpfn); + } else { + ft = File.createTempFile("ssrc_", ".tmp"); + } + try (FileOutputStream tfos= new FileOutputStream(ft)) { + fpto = tfos.getChannel(); + //System.err.printf("nch: %d, bps: %d, size: %d, sfrq: %d, dfrq: %d, ???: %d, ???: %d, twopass: %b, dither: %d\n", nch, bps, 8, sfrq, dfrq, 1, length / bps / nch, twopass, dither); - Resampler resampler; - if (sfrq < dfrq) { - resampler = new Upsampler(); - } else if (sfrq > dfrq) { - resampler = new Downsampler(); - } else { - resampler = new NoSrc(); - } - if (normalize) { - resampler.init(nch, bps, 8, sfrq, dfrq, 1, length / bps / nch, twopass, dither); - } else { - resampler.init(nch, bps, 8, sfrq, dfrq, Math.pow(10, -att / 20), length / bps / nch, twopass, dither); - } - resampler.resample(fpi, fpto); - peak[0] = resampler.peak; - - fpto.close(); - } - - if (!quiet) { - System.err.printf("\npeak : %gdB\n", 20 * Math.log10(peak[0])); - } - - if (!normalize) { - if (peak[0] < Math.pow(10, -att / 20)) { - peak[0] = 1; - } else { - peak[0] *= Math.pow(10, att / 20); - } - } else { - peak[0] *= Math.pow(10, att / 20); - } - - if (!quiet) { - System.err.printf("\nPass 2\n"); - } - - if (dither != 0) { - switch (dbps) { - case 1: - gain = (normalize || peak[0] >= (0x7f - samp) / (double) 0x7f) ? 1 / peak[0] * (0x7f - samp) : 1 / peak[0] * 0x7f; - break; - case 2: - gain = (normalize || peak[0] >= (0x7fff - samp) / (double) 0x7fff) ? 1 / peak[0] * (0x7fff - samp) : 1 / peak[0] * 0x7fff; - break; - case 3: - gain = (normalize || peak[0] >= (0x7fffff - samp) / (double) 0x7fffff) ? 1 / peak[0] * (0x7fffff - samp) : 1 / peak[0] * 0x7fffff; - break; - } - } else { - switch (dbps) { - case 1: - gain = 1 / peak[0] * 0x7f; - break; - case 2: - gain = 1 / peak[0] * 0x7fff; - break; - case 3: - gain = 1 / peak[0] * 0x7fffff; - break; - } - } - randptr = 0; - - setstarttime(); - - fptlen = (int) (ft.length() / 8); + Resampler resampler; + if (sfrq < dfrq) { + resampler = new Upsampler(); + } else if (sfrq > dfrq) { + resampler = new Downsampler(); + } else { + resampler = new NoSrc(); + } + if (normalize) { + resampler.init(nch, bps, 8, sfrq, dfrq, 1, length / bps / nch, twopass, dither); + } else { + resampler.init(nch, bps, 8, sfrq, dfrq, Math.pow(10, -att / 20), length / bps / nch, twopass, dither); + } + resampler.resample(fpi, fpto); + peak[0] = resampler.peak; + + fpto.close(); + } + + if (!quiet) { + System.err.printf("\npeak : %gdB\n", 20 * Math.log10(peak[0])); + } + + if (!normalize) { + if (peak[0] < Math.pow(10, -att / 20)) { + peak[0] = 1; + } else { + peak[0] *= Math.pow(10, att / 20); + } + } else { + peak[0] *= Math.pow(10, att / 20); + } + + if (!quiet) { + System.err.printf("\nPass 2\n"); + } + + if (dither != 0) { + switch (dbps) { + case 1: + gain = (normalize || peak[0] >= (0x7f - samp) / (double) 0x7f) ? 1 / peak[0] * (0x7f - samp) : 1 / peak[0] * 0x7f; + break; + case 2: + gain = (normalize || peak[0] >= (0x7fff - samp) / (double) 0x7fff) ? 1 / peak[0] * (0x7fff - samp) : 1 / peak[0] * 0x7fff; + break; + case 3: + gain = (normalize || peak[0] >= (0x7fffff - samp) / (double) 0x7fffff) ? 1 / peak[0] * (0x7fffff - samp) : 1 / peak[0] * 0x7fffff; + break; + } + } else { + switch (dbps) { + case 1: + gain = 1 / peak[0] * 0x7f; + break; + case 2: + gain = 1 / peak[0] * 0x7fff; + break; + case 3: + gain = 1 / peak[0] * 0x7fffff; + break; + } + } + randptr = 0; + + setstarttime(); + + fptlen = (int) (ft.length() / 8); //System.err.println("tmp: " + fpt.getFilePointer()); - - try (FileInputStream fisf = new FileInputStream(ft)) { - FileChannel fpti = fisf.getChannel(); - ByteBuffer leis = ByteBuffer.allocate(8); - for (sumread = 0; sumread < fptlen;) { - double f; - int s; - - leis.clear(); - fpti.read(leis); - leis.flip(); - f = leis.getDouble(); + + try (FileInputStream fisf = new FileInputStream(ft)) { + FileChannel fpti = fisf.getChannel(); + ByteBuffer leis = ByteBuffer.allocate(8); + for (sumread = 0; sumread < fptlen;) { + double f; + int s; + + leis.clear(); + fpti.read(leis); + leis.flip(); + f = leis.getDouble(); //if (sumread < 100) { // System.err.printf("2: %06d: %f\n", sumread, f); //} - f *= gain; - sumread++; - - switch (dbps) { - case 1: { - s = dither != 0 ? do_shaping(f, peak, dither, ch) : RINT(f); - - ByteBuffer buf = ByteBuffer.allocate(1); - buf.put((byte) (s + 128)); - buf.flip(); - - fpo.write(buf); - } - break; - case 2: { - s = dither != 0 ? do_shaping(f, peak, dither, ch) : RINT(f); - - ByteBuffer buf = ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN); - buf.putShort((short) s); - buf.flip(); - - fpo.write(buf); - } - break; - case 3: { - s = dither != 0 ? do_shaping(f, peak, dither, ch) : RINT(f); - - ByteBuffer buf = ByteBuffer.allocate(3); - buf.put((byte) (s & 255)); - s >>= 8; - buf.put((byte) (s & 255)); - s >>= 8; - buf.put((byte) (s & 255)); - buf.flip(); - - fpo.write(buf); - } - break; - } - - ch++; - if (ch == nch) { - ch = 0; - } - - if ((sumread & 0x3ffff) == 0) { - showprogress((double) sumread / fptlen); - } - } - showprogress(1); - if (!quiet) { - System.err.printf("\n"); - } - fpti.close(); - } - if (ft != null) { + f *= gain; + sumread++; + + switch (dbps) { + case 1: { + s = dither != 0 ? do_shaping(f, peak, dither, ch) : RINT(f); + + ByteBuffer buf = ByteBuffer.allocate(1); + buf.put((byte) (s + 128)); + buf.flip(); + + fpo.write(buf); + } + break; + case 2: { + s = dither != 0 ? do_shaping(f, peak, dither, ch) : RINT(f); + + ByteBuffer buf = ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN); + buf.putShort((short) s); + buf.flip(); + + fpo.write(buf); + } + break; + case 3: { + s = dither != 0 ? do_shaping(f, peak, dither, ch) : RINT(f); + + ByteBuffer buf = ByteBuffer.allocate(3); + buf.put((byte) (s & 255)); + s >>= 8; + buf.put((byte) (s & 255)); + s >>= 8; + buf.put((byte) (s & 255)); + buf.flip(); + + fpo.write(buf); + } + break; + } + + ch++; + if (ch == nch) { + ch = 0; + } + + if ((sumread & 0x3ffff) == 0) { + showprogress((double) sumread / fptlen); + } + } + showprogress(1); + if (!quiet) { + System.err.printf("\n"); + } + fpti.close(); + } + if (ft != null) { //System.err.println("ft: " + ft); - if (ft.delete() == false) { - System.err.printf("Failed to remove %s\n", ft); - } - } - } else { - Resampler resampler; - if (sfrq < dfrq) { - resampler = new Upsampler(); - } else if (sfrq > dfrq) { - resampler = new Downsampler(); - } else { - resampler = new NoSrc(); - } - resampler.init(nch, bps, dbps, sfrq, dfrq, Math.pow(10, -att / 20), length / bps / nch, twopass, dither); - resampler.resample(fpi, fpto); - peak[0] = resampler.peak; - if (!quiet) { - System.err.printf("\n"); - } - } - - if (dither != 0) { - quit_shaper(nch); - } - - if (!twopass && peak[0] > 1) { - if (!quiet) { - System.err.printf("clipping detected : %gdB\n", 20 * Math.log10(peak[0])); - } - } + if (ft.delete() == false) { + System.err.printf("Failed to remove %s\n", ft); + } + } + } else { + Resampler resampler; + if (sfrq < dfrq) { + resampler = new Upsampler(); + } else if (sfrq > dfrq) { + resampler = new Downsampler(); + } else { + resampler = new NoSrc(); + } + resampler.init(nch, bps, dbps, sfrq, dfrq, Math.pow(10, -att / 20), length / bps / nch, twopass, dither); + resampler.resample(fpi, fpto); + peak[0] = resampler.peak; + if (!quiet) { + System.err.printf("\n"); + } + } + + if (dither != 0) { + quit_shaper(nch); + } + + if (!twopass && peak[0] > 1) { + if (!quiet) { + System.err.printf("clipping detected : %gdB\n", 20 * Math.log10(peak[0])); + } + } int len; @@ -2281,24 +2281,24 @@ public void exec(String[] argv) throws IOException { len = (int) fo.length(); try (RandomAccessFile raf = new RandomAccessFile(fo, "rw")) { - fpo = raf.getChannel(); - leos = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN); - - dword = len - 8; - leos.position(0); - leos.limit(4); - leos.putInt(dword); - leos.flip(); - fpo.write(leos, 4); - - dword = len - 44; - leos.position(0); - leos.limit(4); - leos.putInt(dword); - leos.flip(); - fpo.write(leos, 40); - - fpo.close(); + fpo = raf.getChannel(); + leos = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN); + + dword = len - 8; + leos.position(0); + leos.limit(4); + leos.putInt(dword); + leos.flip(); + fpo.write(leos, 4); + + dword = len - 44; + leos.position(0); + leos.limit(4); + leos.putInt(dword); + leos.flip(); + fpo.write(leos, 40); + + fpo.close(); } } } @@ -2393,147 +2393,147 @@ void io(ReadableByteChannel fpi, WritableByteChannel fpo, int length, int nch, i file.deleteOnExit(); try (FileInputStream fis = new FileInputStream(file); FileOutputStream fos = new FileOutputStream(file)) { - FileChannel pipeIn = fis.getChannel(); - FileChannel pipeOut = fos.getChannel(); - - if (!quiet) { - System.err.printf("Pass 1\n"); - } - + FileChannel pipeIn = fis.getChannel(); + FileChannel pipeOut = fos.getChannel(); + + if (!quiet) { + System.err.printf("Pass 1\n"); + } + logger.fine(String.format("nch: %d, bps: %d, size: %d, sfrq: %d, dfrq: %d, ???: %d, ???: %d, twopass: %b, dither: %d\n", nch, bps, 8, sfrq, dfrq, 1, length / bps / nch, twopass, dither)); - Resampler resampler; - if (sfrq < dfrq) { - resampler = new Upsampler(); - } else if (sfrq > dfrq) { - resampler = new Downsampler(); - } else { - resampler = new NoSrc(); - } - if (normalize) { - resampler.init(nch, bps, 8, sfrq, dfrq, 1, length / bps / nch, twopass, dither); - } else { - resampler.init(nch, bps, 8, sfrq, dfrq, Math.pow(10, -att / 20), length / bps / nch, twopass, dither); - } - fptlen = resampler.resample(fpi, pipeOut); - peak[0] = resampler.peak; - - pipeOut.close(); - - if (!quiet) { - System.err.printf("\npeak : %gdB\n", 20 * Math.log10(peak[0])); - } - - if (!normalize) { - if (peak[0] < Math.pow(10, -att / 20)) { - peak[0] = 1; - } else { - peak[0] *= Math.pow(10, att / 20); - } - } else { - peak[0] *= Math.pow(10, att / 20); - } - - if (!quiet) { - System.err.printf("\nPass 2\n"); - } - - if (dither != 0) { - switch (dbps) { - case 1: - gain = (normalize || peak[0] >= (0x7f - samp) / (double) 0x7f) ? 1 / peak[0] * (0x7f - samp) : 1 / peak[0] * 0x7f; - break; - case 2: - gain = (normalize || peak[0] >= (0x7fff - samp) / (double) 0x7fff) ? 1 / peak[0] * (0x7fff - samp) : 1 / peak[0] * 0x7fff; - break; - case 3: - gain = (normalize || peak[0] >= (0x7fffff - samp) / (double) 0x7fffff) ? 1 / peak[0] * (0x7fffff - samp) : 1 / peak[0] * 0x7fffff; - break; - } - } else { - switch (dbps) { - case 1: - gain = 1 / peak[0] * 0x7f; - break; - case 2: - gain = 1 / peak[0] * 0x7fff; - break; - case 3: - gain = 1 / peak[0] * 0x7fffff; - break; - } - } - randptr = 0; - - setstarttime(); - - fptlen /= 8; - - ByteBuffer leis = ByteBuffer.allocate(8); - for (sumread = 0; sumread < fptlen;) { - double f; - int s; - - leis.clear(); - pipeIn.read(leis); - leis.flip(); - f = leis.getDouble(); + Resampler resampler; + if (sfrq < dfrq) { + resampler = new Upsampler(); + } else if (sfrq > dfrq) { + resampler = new Downsampler(); + } else { + resampler = new NoSrc(); + } + if (normalize) { + resampler.init(nch, bps, 8, sfrq, dfrq, 1, length / bps / nch, twopass, dither); + } else { + resampler.init(nch, bps, 8, sfrq, dfrq, Math.pow(10, -att / 20), length / bps / nch, twopass, dither); + } + fptlen = resampler.resample(fpi, pipeOut); + peak[0] = resampler.peak; + + pipeOut.close(); + + if (!quiet) { + System.err.printf("\npeak : %gdB\n", 20 * Math.log10(peak[0])); + } + + if (!normalize) { + if (peak[0] < Math.pow(10, -att / 20)) { + peak[0] = 1; + } else { + peak[0] *= Math.pow(10, att / 20); + } + } else { + peak[0] *= Math.pow(10, att / 20); + } + + if (!quiet) { + System.err.printf("\nPass 2\n"); + } + + if (dither != 0) { + switch (dbps) { + case 1: + gain = (normalize || peak[0] >= (0x7f - samp) / (double) 0x7f) ? 1 / peak[0] * (0x7f - samp) : 1 / peak[0] * 0x7f; + break; + case 2: + gain = (normalize || peak[0] >= (0x7fff - samp) / (double) 0x7fff) ? 1 / peak[0] * (0x7fff - samp) : 1 / peak[0] * 0x7fff; + break; + case 3: + gain = (normalize || peak[0] >= (0x7fffff - samp) / (double) 0x7fffff) ? 1 / peak[0] * (0x7fffff - samp) : 1 / peak[0] * 0x7fffff; + break; + } + } else { + switch (dbps) { + case 1: + gain = 1 / peak[0] * 0x7f; + break; + case 2: + gain = 1 / peak[0] * 0x7fff; + break; + case 3: + gain = 1 / peak[0] * 0x7fffff; + break; + } + } + randptr = 0; + + setstarttime(); + + fptlen /= 8; + + ByteBuffer leis = ByteBuffer.allocate(8); + for (sumread = 0; sumread < fptlen;) { + double f; + int s; + + leis.clear(); + pipeIn.read(leis); + leis.flip(); + f = leis.getDouble(); //if (sumread < 100) { // System.err.printf("2: %06d: %f\n", sumread, f); //} - f *= gain; - sumread++; - - switch (dbps) { - case 1: { - s = dither != 0 ? do_shaping(f, peak, dither, ch) : RINT(f); - - ByteBuffer buf = ByteBuffer.allocate(1); - buf.put((byte) (s + 128)); - buf.flip(); - - fpo.write(buf); - } - break; - case 2: { - s = dither != 0 ? do_shaping(f, peak, dither, ch) : RINT(f); - - ByteBuffer buf = ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN); - buf.putShort((short) s); - buf.flip(); - - fpo.write(buf); - } - break; - case 3: { - s = dither != 0 ? do_shaping(f, peak, dither, ch) : RINT(f); - - ByteBuffer buf = ByteBuffer.allocate(3); - buf.put((byte) (s & 255)); - s >>= 8; - buf.put((byte) (s & 255)); - s >>= 8; - buf.put((byte) (s & 255)); - buf.flip(); - - fpo.write(buf); - } - break; - } - - ch++; - if (ch == nch) { - ch = 0; - } - - if ((sumread & 0x3ffff) == 0) { - showprogress((double) sumread / fptlen); - } - } - showprogress(1); - if (!quiet) { - System.err.printf("\n"); - } - pipeIn.close(); + f *= gain; + sumread++; + + switch (dbps) { + case 1: { + s = dither != 0 ? do_shaping(f, peak, dither, ch) : RINT(f); + + ByteBuffer buf = ByteBuffer.allocate(1); + buf.put((byte) (s + 128)); + buf.flip(); + + fpo.write(buf); + } + break; + case 2: { + s = dither != 0 ? do_shaping(f, peak, dither, ch) : RINT(f); + + ByteBuffer buf = ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN); + buf.putShort((short) s); + buf.flip(); + + fpo.write(buf); + } + break; + case 3: { + s = dither != 0 ? do_shaping(f, peak, dither, ch) : RINT(f); + + ByteBuffer buf = ByteBuffer.allocate(3); + buf.put((byte) (s & 255)); + s >>= 8; + buf.put((byte) (s & 255)); + s >>= 8; + buf.put((byte) (s & 255)); + buf.flip(); + + fpo.write(buf); + } + break; + } + + ch++; + if (ch == nch) { + ch = 0; + } + + if ((sumread & 0x3ffff) == 0) { + showprogress((double) sumread / fptlen); + } + } + showprogress(1); + if (!quiet) { + System.err.printf("\n"); + } + pipeIn.close(); } } else { Resampler resampler; diff --git a/src/main/java/vavi/sound/readme.md b/src/main/java/vavi/sound/readme.md new file mode 100644 index 0000000..f362eac --- /dev/null +++ b/src/main/java/vavi/sound/readme.md @@ -0,0 +1,11 @@ +# vavi.sound + +サウンド関連のクラスを提供します. + + * vavi.sound.adpcm.* ... adpcm + * vavi.sound.mfi.* ... i-melody + * vavi.sound.smaf.* ... smaf + * vavi.sound.midi.* ... i-melody and smaf adpcm + * vavi.sound.mobile.* ... mobile adpcm + * vavi.sound.sampled.ssrc.* ... sampling rate converter + * vavi.sound.sampled.adpcm.* ... adpcm as spi diff --git a/src/main/java/vavi/sound/sampled/mfi/MachineDependentMfiWithVoiceMaker.java b/src/main/java/vavi/sound/sampled/mfi/MachineDependentMfiWithVoiceMaker.java index 07f4802..337f805 100644 --- a/src/main/java/vavi/sound/sampled/mfi/MachineDependentMfiWithVoiceMaker.java +++ b/src/main/java/vavi/sound/sampled/mfi/MachineDependentMfiWithVoiceMaker.java @@ -17,6 +17,10 @@ /** * MachineDependentMfiWithVoiceMaker. + *
    + * properties file ... "/vavi/sound/sampled/mfi/MfiWithVoiceMaker.properties"
    + * name prefix ... "class."
    + * 
    * * @author Naohide Sano (nsano) * @version 0.00 050403 nsano initial version
    @@ -33,7 +37,7 @@ public interface MachineDependentMfiWithVoiceMaker { List getEvents(byte[] data, float time, int sampleRate, int bits, int channels, int masterVolume, int adpcmVolume) throws InvalidMfiDataException, IOException; - /** */ + /** factory */ static final PrefixedPropertiesFactory factory = new PrefixedClassPropertiesFactory("/vavi/sound/sampled/mfi/MfiWithVoiceMaker.properties", "class.") { diff --git a/src/main/java/vavi/sound/sampled/mfi/MfiWithVoiceMaker.java b/src/main/java/vavi/sound/sampled/mfi/MfiWithVoiceMaker.java index 0a324a1..5ae72b3 100644 --- a/src/main/java/vavi/sound/sampled/mfi/MfiWithVoiceMaker.java +++ b/src/main/java/vavi/sound/sampled/mfi/MfiWithVoiceMaker.java @@ -168,6 +168,10 @@ protected int createMFi(byte[] data, File file) throws InvalidMfiDataException, message = new EndOfTrackMessage(0, 0); track.add(new MfiEvent(message, 0l)); + if (!file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + int r = MfiSystem.write(sequence, VaviMfiFileFormat.FILE_TYPE, file); Debug.println("write: " + r); return r; diff --git a/src/main/java/vavi/sound/sampled/mfi/package.html b/src/main/java/vavi/sound/sampled/mfi/package.html deleted file mode 100644 index 1b2903f..0000000 --- a/src/main/java/vavi/sound/sampled/mfi/package.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - -vavi.sound.sampled.mfi - - - - - -

    -MFi ADPCM サウンド関連の javax.sound.sampled.spi 実装クラスを提供します. -

    - -

    これから実装すること

    - -
      -
    • WaveDivider のステレオ対応
    • -
    • Zip で本来のアウトプットに出力する
    • -
    - -
    -
    - - - diff --git a/src/main/java/vavi/sound/sampled/mfi/readme.md b/src/main/java/vavi/sound/sampled/mfi/readme.md new file mode 100644 index 0000000..16995ef --- /dev/null +++ b/src/main/java/vavi/sound/sampled/mfi/readme.md @@ -0,0 +1,8 @@ +# vavi.sound.sampled.mfi + +MFi ADPCM サウンド関連の javax.sound.sampled.spi 実装クラスを提供します. + +## TODO + + * WaveDivider のステレオ対応 + * Zip で本来のアウトプットに出力する diff --git a/src/main/java/vavi/sound/sampled/smaf/DividedSmafWithVoiceMaker.java b/src/main/java/vavi/sound/sampled/smaf/DividedSmafWithVoiceMaker.java index 9cbf524..7a3ff00 100644 --- a/src/main/java/vavi/sound/sampled/smaf/DividedSmafWithVoiceMaker.java +++ b/src/main/java/vavi/sound/sampled/smaf/DividedSmafWithVoiceMaker.java @@ -8,6 +8,7 @@ import java.io.File; import java.io.IOException; +import java.util.logging.Level; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; @@ -68,6 +69,7 @@ private class Event implements WaveDivider.Event { public void exec(WaveDivider.Chunk chunk) throws IOException { try { File file = new File(directory, String.format(base, chunk.sequence + 1)); +Debug.println(Level.FINE, "file: " + file + ", " + directory + ", " + base + ", " + (chunk.sequence + 1)); r += createSMAF(chunk.buffer, file); } catch (InvalidSmafDataException e) { throw (IOException) new IOException().initCause(e); diff --git a/src/main/java/vavi/sound/sampled/smaf/SMAF.java b/src/main/java/vavi/sound/sampled/smaf/SMAF.java index 57867af..86c67cc 100644 --- a/src/main/java/vavi/sound/sampled/smaf/SMAF.java +++ b/src/main/java/vavi/sound/sampled/smaf/SMAF.java @@ -22,8 +22,8 @@ public class SMAF extends Type { /** * @param properties keys are followings. *
    -     * "smaf.directory" String: output base directory
    -     * "smaf.base" String: output file template (use {@link String#format(String, Object...)})
    +     * "smaf.directory" String: output base directory, after this "mmf" directory will be added
    +     * "smaf.base" String: output file template (use {@link String#format(String, Object...)}) need extension, like "foo_%d.mmf"
          * "smaf.time" float: dividing time in [sec]
          * "smaf.sampleRate" int: ADPCM sampling rate [Hz]
          * "smaf.bits" int: ADPCM sampling bits
    diff --git a/src/main/java/vavi/sound/sampled/smaf/SmafAudioFileWriter.java b/src/main/java/vavi/sound/sampled/smaf/SmafAudioFileWriter.java
    index 8892152..314d87b 100644
    --- a/src/main/java/vavi/sound/sampled/smaf/SmafAudioFileWriter.java
    +++ b/src/main/java/vavi/sound/sampled/smaf/SmafAudioFileWriter.java
    @@ -84,10 +84,8 @@ public int write(AudioInputStream stream, Type fileType, OutputStream out) throw
                     int r = mwvm.create();
                     return r;
                 }
    -        } catch (UnsupportedAudioFileException e) {
    -            throw (IOException) new IOException().initCause(e);
    -        } catch (InvalidSmafDataException e) {
    -            throw (IOException) new IOException().initCause(e);
    +        } catch (UnsupportedAudioFileException | InvalidSmafDataException e) {
    +            throw new IOException(e);
             }
         }
     
    diff --git a/src/main/java/vavi/sound/sampled/smaf/SmafWithVoiceMaker.java b/src/main/java/vavi/sound/sampled/smaf/SmafWithVoiceMaker.java
    index e969d4a..8c285ff 100644
    --- a/src/main/java/vavi/sound/sampled/smaf/SmafWithVoiceMaker.java
    +++ b/src/main/java/vavi/sound/sampled/smaf/SmafWithVoiceMaker.java
    @@ -240,6 +240,9 @@ protected int createSMAF(byte[] data, File file) throws InvalidSmafDataException
             fileChunk.setContentsInfoChunk(contentsInfoChunk);
             fileChunk.addPcmAudioTrackChunk(pcmAudioTrackChunk);
     
    +        if (!file.getParentFile().exists()) {
    +            file.getParentFile().mkdirs();
    +        }
             fileChunk.writeTo(new FileOutputStream(file));
             int r = fileChunk.getSize();
     Debug.println("write: " + r);
    diff --git a/src/main/java/vavi/sound/sampled/smaf/package.html b/src/main/java/vavi/sound/sampled/smaf/package.html
    deleted file mode 100644
    index b5e4543..0000000
    --- a/src/main/java/vavi/sound/sampled/smaf/package.html
    +++ /dev/null
    @@ -1,39 +0,0 @@
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -vavi.sound.sampled.smaf
    -
    -
    -
    -
    -
    -

    -SMAF ADPCM サウンド関連の javax.sound.sampled.spi 実装クラスを提供します. -

    - -

    これから実装すること

    - -
      -
    • -
    - -
    -
    - - - diff --git a/src/main/java/vavi/sound/sampled/smaf/readme.md b/src/main/java/vavi/sound/sampled/smaf/readme.md new file mode 100644 index 0000000..b73f41a --- /dev/null +++ b/src/main/java/vavi/sound/sampled/smaf/readme.md @@ -0,0 +1,5 @@ +# vavi.sound.smapled.smaf + +SMAF ADPCM サウンド関連の javax.sound.sampled.spi 実装クラスを提供します. + +## TODO diff --git a/src/main/java/vavi/sound/smaf/MetaEventAdapter.java b/src/main/java/vavi/sound/smaf/MetaEventAdapter.java index 492f643..eadee39 100644 --- a/src/main/java/vavi/sound/smaf/MetaEventAdapter.java +++ b/src/main/java/vavi/sound/smaf/MetaEventAdapter.java @@ -10,7 +10,7 @@ import javax.sound.midi.MetaEventListener; -import vavi.sound.midi.MidiConstants; +import vavi.sound.midi.MidiConstants.MetaEvent; import vavi.sound.midi.MidiUtil; import vavi.sound.midi.VaviMidiDeviceProvider; import vavi.sound.smaf.message.MidiContext; @@ -60,8 +60,8 @@ public void open() { */ public void meta(javax.sound.midi.MetaMessage message) { //Debug.println("type: " + message.getType()); - switch (message.getType()) { - case MidiConstants.META_MACHINE_DEPEND: // シーケンサ固有のメタイベント + switch (MetaEvent.valueOf(message.getType())) { + case META_MACHINE_DEPEND: // シーケンサ固有のメタイベント try { processSpecial(message); } catch (InvalidSmafDataException e) { @@ -74,13 +74,13 @@ public void meta(javax.sound.midi.MetaMessage message) { throw e; } break; - case MidiConstants.META_TEXT_EVENT: // テキスト・イベント - case MidiConstants.META_COPYRIGHT: // 著作権表示 - case MidiConstants.META_NAME: // シーケンス名またはトラック名 + case META_TEXT_EVENT: // テキスト・イベント + case META_COPYRIGHT: // 著作権表示 + case META_NAME: // シーケンス名またはトラック名 Debug.println("meta " + message.getType() + ": " + MidiUtil.getDecodedMessage(message.getData())); break; - case MidiConstants.META_END_OF_TRACK: // トラックの終わり - case MidiConstants.META_TEMPO: // テンポ設定 + case META_END_OF_TRACK: // トラックの終わり + case META_TEMPO: // テンポ設定 Debug.println(Level.FINE, "this handler ignore meta: " + message.getType()); break; default: diff --git a/src/main/java/vavi/sound/smaf/SmafFileFormat.java b/src/main/java/vavi/sound/smaf/SmafFileFormat.java index d163124..30878a9 100644 --- a/src/main/java/vavi/sound/smaf/SmafFileFormat.java +++ b/src/main/java/vavi/sound/smaf/SmafFileFormat.java @@ -68,22 +68,28 @@ Sequence getSequence() { return sequence; } - /** */ + /** factory */ static SmafFileFormat readFrom(InputStream is) throws InvalidSmafDataException, IOException { - Chunk chunk = Chunk.readFrom(is, null, true); - if (FileChunk.class.isInstance(chunk)) { - FileChunk fileChunk = FileChunk.class.cast(chunk); - SmafFileFormat sff = new SmafFileFormat(fileChunk.getSize()); - sff.sequence = new SmafSequence(fileChunk); - return sff; - } else { - throw new InvalidSmafDataException("stream is not smaf"); + try { + Chunk chunk = Chunk.readFrom(is, null); + if (FileChunk.class.isInstance(chunk)) { + FileChunk fileChunk = FileChunk.class.cast(chunk); + SmafFileFormat sff = new SmafFileFormat(fileChunk.getSize()); + sff.sequence = new SmafSequence(fileChunk); + return sff; + } else { + throw new InvalidSmafDataException("stream is not smaf: first chunk: " + chunk.getId()); + } + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new InvalidSmafDataException(e); } } /** * ストリームに書き込みます。事前にシーケンスを設定しておくこと。 - * @after out は {@link java.io.OutputStream#flush() flush} されます + * @after out has been {@link java.io.OutputStream#flush() flush}-ed * @throws IllegalStateException シーケンスが設定されていない場合スローされます */ void writeTo(OutputStream out) @@ -112,7 +118,7 @@ void writeTo(OutputStream out) track.writeTo(out); } - out.flush(); // TODO いる? + out.flush(); // TODO is needed? byteLength = smafDataLength + 4 + 4; } diff --git a/src/main/java/vavi/sound/smaf/SmafMessage.java b/src/main/java/vavi/sound/smaf/SmafMessage.java index 7b0975a..c9c7b60 100644 --- a/src/main/java/vavi/sound/smaf/SmafMessage.java +++ b/src/main/java/vavi/sound/smaf/SmafMessage.java @@ -6,10 +6,6 @@ package vavi.sound.smaf; -import java.io.IOException; -import java.io.OutputStream; - - /** * SMAF メッセージの基底クラスです. * @@ -42,21 +38,6 @@ public int getDuration() { /** */ public abstract int getLength(); - - /** */ - protected void writeOneToTwo(OutputStream os, int value) throws IOException { - if (value < 128) { - os.write(value); - } else { - os.write(0x80 | (value - 0x80) / 0x80); - os.write((value - 0x80) % 0x80); - } - } - - /** */ - protected void writeOneToFour(OutputStream os, int value) throws IOException { - // TODO - } } /* */ diff --git a/src/main/java/vavi/sound/smaf/SmafSequencer.java b/src/main/java/vavi/sound/smaf/SmafSequencer.java index 6aa3aeb..bbd5143 100644 --- a/src/main/java/vavi/sound/smaf/SmafSequencer.java +++ b/src/main/java/vavi/sound/smaf/SmafSequencer.java @@ -23,14 +23,9 @@ /** * Sequencer implemented for SMAF. *

    - * このシーケンサクラスで再生する場合は - * システムプロパティ javax.sound.midi.Sequencer"#Real Time Sequencer" - * を明示するようにしてください。"Java MIDI(MFi/SMAF) ADPCM Sequencer" が - * デフォルトシーケンサになった場合、{@link #mea}が重複して登録されてしまいます。 - *

    - *

    - * {@link javax.sound.midi.MidiSystem#getSequencer()} を - * 使用しているため javax.sound.midi SPI のプログラム内で使用してはいけません。 + * don't use {@link javax.sound.midi.MidiSystem#getSequencer()}, + * {@link javax.sound.midi.MidiSystem#getSequencer(boolean)} in this program, + * because this is the {@link javax.sound.midi.Sequencer}. *

    * @author Naohide Sano (nsano) * @version 0.00 071010 nsano initial version
    @@ -53,12 +48,12 @@ class SmafSequencer implements Sequencer, Synthesizer { /** the sequence of SMAF */ private Sequence sequence; - /** */ + @Override public SmafDevice.Info getDeviceInfo() { return info; } - /* */ + @Override public void close() { if (midiSequencer == null) { throw new IllegalStateException("not opend"); @@ -67,7 +62,7 @@ public void close() { midiSynthesizer.close(); } - /* */ + @Override public boolean isOpen() { if (midiSequencer == null) { return false; @@ -75,10 +70,10 @@ public boolean isOpen() { return midiSequencer.isOpen(); } - /** ADPCM sequencer */ + /** ADPCM sequencer, TODO should be {@link javax.sound.midi.Transmitter} */ private javax.sound.midi.MetaEventListener mea = new MetaEventAdapter(); - /* */ + @Override public void open() throws SmafUnavailableException { try { if (midiSequencer == null) { @@ -94,7 +89,7 @@ public void open() throws SmafUnavailableException { } } - /* */ + @Override public void setSequence(Sequence sequence) throws InvalidSmafDataException { @@ -111,7 +106,7 @@ public void setSequence(Sequence sequence) } } - /* */ + @Override public void setSequence(InputStream stream) throws IOException, InvalidSmafDataException { @@ -119,12 +114,12 @@ public void setSequence(InputStream stream) this.setSequence(SmafSystem.getSequence(stream)); } - /* */ + @Override public Sequence getSequence() { return sequence; } - /* */ + @Override public void start() { if (midiSequencer == null) { throw new IllegalStateException("not opend"); @@ -133,7 +128,7 @@ public void start() { midiSequencer.start(); } - /* */ + @Override public void stop() { if (midiSequencer == null) { throw new IllegalStateException("not opend"); @@ -142,7 +137,7 @@ public void stop() { off(); } - /* */ + @Override public boolean isRunning() { if (midiSequencer == null) { throw new IllegalStateException("not opend"); @@ -186,7 +181,7 @@ protected void fireMeta(MetaMessage meta) { public void meta(javax.sound.midi.MetaMessage message) { //Debug.println("type: " + message.getType()); switch (message.getType()) { - case 0x2f: // 自動的に最後につけてくれる + case 0x2f: // added automatically at the end of the sequence try { MetaMessage metaMessage = new MetaMessage(); metaMessage.setMessage(0x2f, null); diff --git a/src/main/java/vavi/sound/smaf/chunk/AudioSequenceDataChunk.java b/src/main/java/vavi/sound/smaf/chunk/AudioSequenceDataChunk.java index 5148dd2..0ef722e 100644 --- a/src/main/java/vavi/sound/smaf/chunk/AudioSequenceDataChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/AudioSequenceDataChunk.java @@ -7,7 +7,6 @@ package vavi.sound.smaf.chunk; import java.io.IOException; -import java.io.InputStream; import vavi.sound.smaf.InvalidSmafDataException; import vavi.sound.smaf.SmafMessage; @@ -39,14 +38,14 @@ public AudioSequenceDataChunk() { } /** TODO how to get formatType from parent chunk ??? */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { //Debug.println("available: " + is.available() + ", " + available()); //skip(is, size); // TODO FormatType formatType = ((TrackChunk) parent).getFormatType(); switch (formatType) { case HandyPhoneStandard: - readHandyPhoneStandard(is); + readHandyPhoneStandard(dis); break; default: throw new InvalidSmafDataException("FormatType: " + formatType); diff --git a/src/main/java/vavi/sound/smaf/chunk/BitmapChunk.java b/src/main/java/vavi/sound/smaf/chunk/BitmapChunk.java index 33a6cfb..9027bb0 100644 --- a/src/main/java/vavi/sound/smaf/chunk/BitmapChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/BitmapChunk.java @@ -7,7 +7,6 @@ package vavi.sound.smaf.chunk; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import vavi.sound.smaf.InvalidSmafDataException; @@ -37,9 +36,9 @@ public BitmapChunk() { } /** */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { -skip(is, size); // TODO +dis.skipBytes((int) (long) size); // TODO } /** TODO */ diff --git a/src/main/java/vavi/sound/smaf/chunk/Chunk.java b/src/main/java/vavi/sound/smaf/chunk/Chunk.java index fc22085..27f3b1f 100644 --- a/src/main/java/vavi/sound/smaf/chunk/Chunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/Chunk.java @@ -6,8 +6,8 @@ package vavi.sound.smaf.chunk; +import java.io.DataInput; import java.io.DataInputStream; -import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -16,6 +16,7 @@ import java.util.logging.Level; import vavi.sound.smaf.InvalidSmafDataException; +import vavi.util.ByteUtil; import vavi.util.Debug; import vavi.util.properties.PrefixedPropertiesFactory; @@ -35,17 +36,6 @@ public abstract class Chunk { /** Chunk size */ protected int size; - /** - * 親でカウントダウンしないで済むように。 - * (結局ややこしいだけちゃうん?) - * @see #Chunk(byte[], int) - * @see #available() - * @see #read(InputStream) - * @see #skip(InputStream,long) - * @see #read(InputStream,byte[]) - */ - private int readSize; - /** */ public Chunk() { } @@ -55,18 +45,16 @@ protected Chunk(byte[] id, int size) { this.id = id; this.size = size; - - this.readSize = size; } /** - * @param is Chunk Header は読み込み済みであること + * @param dis Chunk Header は読み込み済みであること * @throws IOException * @throws InvalidSmafDataException * TODO Chunk -> constructor ??? * TODO parent を渡したいが為。 */ - protected abstract void init(InputStream is, Chunk parent) + protected abstract void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException; /** Chunk ID */ @@ -79,91 +67,6 @@ public int getSize() { return size; } - /** - * カウントダウンした結果 - * @see #readSize - */ - protected int available() { - return readSize; - } - - /** - * 勝手にカウントダウンしない InputStream から直接読み込んだ場合の補正用 - * @see #readSize - */ - private void consume(int size) { - readSize -= size; - } - - /** - * EOF チェック付きのユーティリティ - * @see #readSize カウントダウンされます - */ - protected void skip(InputStream is, long bytes) throws IOException { - skipInternal(is, bytes); - readSize -= bytes; - } - - /** - * EOF チェック付きのユーティリティ - */ - private static void skipInternal(InputStream is, long bytes) throws IOException { - long l = 0; - while (bytes - l > 0) { - long r = is.skip(bytes - l); - if (r < 0) { - throw new EOFException(); - } - l += r; - } - } - - /** - * EOF チェック付きのユーティリティ - * @see #readSize カウントダウンされます - * @return unsigned byte - */ - protected int read(InputStream is) throws IOException { - DataInputStream dis = new DataInputStream(is); - consume(1); - return dis.readUnsignedByte(); - } - - /** - * EOF チェック付きのユーティリティ - * @see #readSize カウントダウンされます - * @return unsigned short - */ - protected int readShort(InputStream is) throws IOException { - DataInputStream dis = new DataInputStream(is); - consume(2); - return dis.readUnsignedShort(); - } - - /** - * EOF チェック付きのユーティリティ - * buffer.length サイズ読み込まれます。 - * @see #readSize カウントダウンされます - */ - protected void read(InputStream is, byte[] buffer) throws IOException { - readInternal(is, buffer); - consume(buffer.length); - } - - /** - * EOF チェック付きのユーティリティ - */ - private static void readInternal(InputStream is, byte[] buffer) throws IOException { - int l = 0; - while (buffer.length - l > 0) { - int r = is.read(buffer, l, buffer.length - l); - if (r < 0) { - throw new EOFException(); - } - l += r; - } - } - /** * 最初でない親の読み込み用(マーク無し) * @param is @@ -172,62 +75,54 @@ private static void readInternal(InputStream is, byte[] buffer) throws IOExcepti protected Chunk readFrom(InputStream is) throws InvalidSmafDataException, IOException { - return readFrom(is, this, false); + return readFrom(is, this); } /** * @param is should support marking * @param parent 親のデータが欲しい時があるので - * @param mark Chunk Header を読み込んだあと破棄するかどうか(最初だけ使う) * @return 読み込んだ Chunk オブジェクト - * @see #readSize parent != null ならカウントダウンされます - * @throws IOException when is does not support marking */ - public static Chunk readFrom(InputStream is, Chunk parent, boolean mark) + public static Chunk readFrom(InputStream is, Chunk parent) throws InvalidSmafDataException, IOException { - if (mark && !is.markSupported()) { - throw new IOException("cannot mark to stream"); - } - - if (mark) { - is.mark(8); + DataInputStream dis; + if (is instanceof MyDataInputStream) { + MyDataInputStream mdis = MyDataInputStream.class.cast(is); + dis = new DataInputStream(mdis.is); + } else { + dis = new DataInputStream(is); } byte[] id = new byte[4]; - readInternal(is, id); + dis.readFully(id); // not want to count down - DataInputStream dis = new DataInputStream(is); int size = dis.readInt(); -Debug.printf(Level.FINE, "size: %1$08x (%1$d)", size); - - if (mark) { - is.reset(); - is.mark(8 + size); - skipInternal(is, 8); - } +Debug.printf(Level.FINE, "size: 0x%1$08x (%1$d)", size); Chunk chunk = newInstance(id, size); - chunk.init(is, parent); - - if (mark) { - is.reset(); - - is.mark(8 + size); - int crcLength = size + 8 - 2; - byte[] buffer = new byte[crcLength]; - readInternal(is, buffer); - - CRC16 crc = new CRC16(); - crc.update(buffer); -Debug.printf(Level.FINE, "crc (calc): %04x", (int) ~crc.getValue()); - - is.reset(); - } +//Debug.println(chunk.getClass().getName() + "\n" + StringUtil.getDump(is, 0, 128)); +//Debug.printf(Level.FINE, "is: " + is + " / " + chunk.getClass().getName()); + MyDataInputStream mdis = new MyDataInputStream(is, id, size); +//Debug.printf(Level.FINE, "mdis: " + mdis + " / " + chunk.getClass().getName()); + chunk.init(mdis, parent); if (parent != null) { // 親のループ内での読み込みの場合 - parent.consume(8 + chunk.getSize()); + if (is instanceof MyDataInputStream) { + mdis = MyDataInputStream.class.cast(is); + mdis.readSize -= 8 + chunk.getSize(); + } else { + assert false : "is: " + is.getClass().getName(); + } + } else { +//Debug.printf(Level.FINE, "crc (calc): %04x, avail: %d, %s, %s", mdis.crc(), mdis.available(), mdis, chunk.getClass().getName()); + if (chunk instanceof FileChunk) { + FileChunk fc = FileChunk.class.cast(chunk); + if (fc.getCrc() != mdis.crc()) { +Debug.printf(Level.WARNING, "crc not match expected: %04x, actural: %04x", fc.getCrc(), mdis.crc()); + } + } } return chunk; @@ -238,6 +133,124 @@ public static Chunk readFrom(InputStream is, Chunk parent, boolean mark) //---- + /** input stream with count down, crc */ + protected static class MyDataInputStream extends InputStream implements DataInput { + InputStream is; + DataInputStream dis; + int readSize; + static ThreadLocal crc = new ThreadLocal<>(); + + protected MyDataInputStream(InputStream is, byte[] id, int size) { + if (is instanceof MyDataInputStream) { + MyDataInputStream mdis = MyDataInputStream.class.cast(is); + this.is = mdis.is; + } else { + this.is = is; + } +//Debug.printf(Level.FINE, "is: " + this.is); + this.dis = new DataInputStream(this.is); + this.readSize = size; + + if (crc.get() == null) { + crc.set(new CRC16()); + } + crc.get().update(id); + crc.get().update(ByteUtil.getBeBytes(size)); + } + public int crc() { +//Debug.println("crc len: " + crc.get().getCount()); + return (int) crc.get().getValue(); + } + @Override + public long skip(long n) throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public int available() throws IOException { + return readSize; + } + @Override + public int readUnsignedByte() throws IOException { + int r = dis.readUnsignedByte(); + crc.get().update((byte) r); + readSize--; + return r; + } + @Override + public void readFully(byte[] b) throws IOException { + dis.readFully(b, 0, b.length); + crc.get().update(b); + readSize -= b.length; + } + @Override + public int read() throws IOException { + return is.read(); + } + @Override + public void readFully(byte[] b, int off, int len) throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public int skipBytes(int n) throws IOException { + byte[] b = new byte[n]; + dis.readFully(b); + crc.get().update(b); + readSize -= n; + return n; + } + @Override + public boolean readBoolean() throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public byte readByte() throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public short readShort() throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public int readUnsignedShort() throws IOException { + int r = dis.readUnsignedShort(); + if (available() > 2) { + // crc is located at last of the file + // and this condition assumed to get crc uses this method. + crc.get().update(ByteUtil.getBeBytes((short) r)); + } + readSize -= 2; + return r; + } + @Override + public char readChar() throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public int readInt() throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public long readLong() throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public float readFloat() throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public double readDouble() throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public String readLine() throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public String readUTF() throws IOException { + throw new UnsupportedOperationException(); + } + } + /** CCITT X.25 */ static class CRC16 { /** number of bits in a char */ @@ -264,6 +277,7 @@ static class CRC16 { /** */ int crc = 0xffff; + int count; /** * 16 ビットの CRC を方法 1 で求めます。 * @param c データを与えます。 @@ -272,6 +286,7 @@ static class CRC16 { public int update(byte[] c) { for (int n = 0; n < c.length; n++) { crc = (crc << BYTE_BIT) ^ crcTable[((crc >> (16 - BYTE_BIT)) & 0xff) ^ (c[n] & 0xff)]; + count++; } return ~crc & 0xffff; } @@ -279,73 +294,25 @@ public int update(byte[] c) { /** */ public int update(byte c) { crc = (crc << BYTE_BIT) ^ crcTable[((crc >> (16 - BYTE_BIT)) & 0xff) ^ (c & 0xff)]; + count++; return ~crc & 0xffff; } /** */ - public long getValue() { - return crc; - } - } - - //---- - - /** - * read 1 ~ 2 bytes - * @return 0〜127, 128〜16511 (0x407f) - */ - protected int readOneToTwo(InputStream is) - throws IOException { - - int value; - int d1 = read(is); -//Debug.println("d1: " + d1 + "(" + StringUtil.toHex2(d1) + ")"); - if ((0x80 & d1) != 0) { // ---- 0x80 ~ 0xff, ---- - int d2 = read(is); -//Debug.println("d2: " + d2 + "(" + StringUtil.toHex2(d2) + ")"); - value = (((d1 & 0x7f) + 1) << 7) | (d2 & 0x7f); - } else { // ---- 0x01 ~ 0x7f, ---- - value = d1 & 0x7f; + public int getValue() { + return ~crc & 0xffff; } -//Debug.println("value: " + value); - return value; - } - /** - * read 1 ~ 4 bytes - * @return 0 ~ 268435455 (0x0fffffff) - */ - protected int readOneToFour(InputStream is) - throws IOException { - - int value; - int d1 = read(is); - if ((0x80 & d1) != 0) { - int d2 = read(is); - if ((0x80 & d2) != 0) { - int d3 = read(is); - if ((0x80 & d3) != 0) { - int d4 = read(is); - value = ((d1 & 0x7f) << 21) | ((d2 & 0x7f) << 14) | ((d3 & 0x7f) << 7) | (d4 & 0x7f); -//Debug.println("1-4(4): " + value); - } else { - value = ((d1 & 0x7f) << 14) | ((d2 & 0x7f) << 7) | (d3 & 0x7f); -//Debug.println("1-4(3): " + value); - } - } else { - value = ((d1 & 0x7f) << 7) | (d2 & 0x7f); // 128 ~ -//Debug.println("1-4(2): " + value); - } - } else { - value = d1 & 0x7f; // 0 ~ 127 -//Debug.println("1-4(1): " + value); + /** */ + public int getCount() { + return count; } - return value; - } +} //---- /** + * factory * @param id a chunk id read * @param size * @return chunk @@ -356,29 +323,30 @@ private static Chunk newInstance(byte[] id, int size) try { return chunkFactory.get(id).newInstance(id, size); } catch (IllegalArgumentException e) { +Debug.println(Level.FINE, e); return new UndefinedChunk(id, size); // TODO out source // throw new InvalidSmafDataException("unsupported chunk id: " + StringUtil.getDump(id)); } catch (Exception e) { if (e instanceof InvocationTargetException) { -Debug.printStackTrace(e.getCause()); +Debug.printStackTrace(Level.SEVERE, e.getCause()); } else { -Debug.printStackTrace(e); +Debug.printStackTrace(Level.SEVERE, e); } throw new IllegalStateException(e); } } - /** */ + /** prefix for property file */ private static final String keyBase = "chunk."; - /** */ + /** constructors for factory */ private static final PrefixedPropertiesFactory> chunkFactory = new PrefixedPropertiesFactory>("/vavi/sound/smaf/smaf.properties", keyBase) { @Override public Constructor get(byte[] id) { String type = new String(id); -Debug.printf(Level.FINE, "Chunk ID(read): %s+0x%02x", (Character.isLetterOrDigit(type.charAt(3)) ? type : new String(id, 0, 3)), type.charAt(3)); +Debug.printf(Level.FINE, "Chunk ID(read): %s+0x%02x", (Character.isLetterOrDigit(type.charAt(3)) ? type : new String(id, 0, 3)), (int) type.charAt(3)); for (String key : instances.keySet()) { if (key.charAt(3) == '*' && key.substring(0, 3).equals(type.substring(0, 3))) { diff --git a/src/main/java/vavi/sound/smaf/chunk/ColorPaletteDefinitionChunk.java b/src/main/java/vavi/sound/smaf/chunk/ColorPaletteDefinitionChunk.java index 3ba382f..e4a1c1f 100644 --- a/src/main/java/vavi/sound/smaf/chunk/ColorPaletteDefinitionChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/ColorPaletteDefinitionChunk.java @@ -8,7 +8,6 @@ import java.io.DataOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import vavi.sound.smaf.InvalidSmafDataException; @@ -37,9 +36,9 @@ public ColorPaletteDefinitionChunk() { } /** */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { -skip(is, size); +dis.skipBytes((int) (long) size); } /** */ diff --git a/src/main/java/vavi/sound/smaf/chunk/ContentsInfoChunk.java b/src/main/java/vavi/sound/smaf/chunk/ContentsInfoChunk.java index 3c39fd5..4cd978a 100644 --- a/src/main/java/vavi/sound/smaf/chunk/ContentsInfoChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/ContentsInfoChunk.java @@ -8,11 +8,11 @@ import java.io.DataOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.Map; import java.util.TreeMap; +import java.util.logging.Level; import vavi.sound.smaf.InvalidSmafDataException; import vavi.util.Debug; @@ -49,30 +49,30 @@ public ContentsInfoChunk() { } /** */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { - this.contentsClass = read(is); -Debug.println("contentsClass: " + (contentsClass == 0 ? "YAMAHA" : "Vender ID(" + contentsClass + ")")); - this.contentsType = read(is); -Debug.printf("contentsType: 0x02x\n", contentsType); - this.contentsCodeType = read(is); -Debug.printf("contentsCodeType: 0x02x\n", contentsCodeType); - this.copyStatus = read(is); -Debug.println("copyStatus: " + StringUtil.toBits(copyStatus, 8)); - this.copyCounts = read(is); -Debug.println("copyCounts: " + copyCounts); + this.contentsClass = dis.readUnsignedByte(); +Debug.println(Level.FINE, "contentsClass: " + (contentsClass == 0 ? "YAMAHA" : "Vender ID(" + contentsClass + ")")); + this.contentsType = dis.readUnsignedByte(); +Debug.printf(Level.FINE, "contentsType: 0x%02x\n", contentsType); + this.contentsCodeType = dis.readUnsignedByte(); +Debug.printf(Level.FINE, "contentsCodeType: 0x%02x\n", contentsCodeType); + this.copyStatus = dis.readUnsignedByte(); +Debug.println(Level.FINE, "copyStatus: " + StringUtil.toBits(copyStatus, 8)); + this.copyCounts = dis.readUnsignedByte(); +Debug.println(Level.FINE, "copyCounts: " + copyCounts); byte[] option = new byte[size - 5]; - read(is, option); -Debug.println("option: " + option.length + " bytes (subData)"); + dis.readFully(option); +Debug.println(Level.FINE, "option: " + option.length + " bytes (subData)"); int i = 0; while (i < option.length) { -//Debug.println(i + " / " + option.length + "\n" + StringUtil.getDump(option, i, option.length - i)); +Debug.println(Level.FINER, i + " / " + option.length + "\n" + StringUtil.getDump(option, i, option.length - i)); SubData subDatum = new SubData(option, i, contentsCodeType); subData.put(subDatum.getTag(), subDatum); -Debug.println("ContentsInfo: subDatum: " + subDatum); +Debug.println(Level.FINE, "ContentsInfo: subDatum: " + subDatum); i += 2 + 1 + subDatum.getData().length + 1; // tag ':' data ',' -//Debug.println(i + " / " + option.length + "\n" + StringUtil.getDump(option, i, option.length - i)); +Debug.println(Level.FINER, i + " / " + option.length + "\n" + StringUtil.getDump(option, i, option.length - i)); } } diff --git a/src/main/java/vavi/sound/smaf/chunk/DataChunk.java b/src/main/java/vavi/sound/smaf/chunk/DataChunk.java index 7e1b980..fac4588 100644 --- a/src/main/java/vavi/sound/smaf/chunk/DataChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/DataChunk.java @@ -6,13 +6,14 @@ package vavi.sound.smaf.chunk; +import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.Map; import java.util.TreeMap; +import java.util.logging.Level; import vavi.sound.smaf.InvalidSmafDataException; import vavi.util.Debug; @@ -34,7 +35,7 @@ public DataChunk(byte[] id, int size) { super(id, size); this.languageCode = id[3] & 0xff; -Debug.println("Data: lang: " + languageCode + ", size: " + size); +Debug.println(Level.FINE, "Data: lang: " + languageCode + ", size: " + size); } /** */ @@ -44,17 +45,17 @@ public DataChunk() { } /** */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { -//Debug.println("available: " + available()); - while (available() > 4) { // TODO 正常ファイルは 0 でいい - SubData subDatum = new SubData(is); -Debug.println(subDatum); +Debug.println(Level.FINER, "available: " + dis.available()); + while (dis.available() > 4) { // TODO 正常ファイルは 0 でいい + SubData subDatum = new SubData(dis); +Debug.println(Level.FINE, subDatum); subData.put(subDatum.tag, subDatum); -//Debug.println("SubData: " + subDatum.tag + ", " + subDatum.data.length + ", " + available()); +Debug.println(Level.FINER, "SubData: " + subDatum.tag + ", " + subDatum.data.length + ", " + dis.available()); } - skip(is, available()); // TODO 正常ファイルなら必要なし + dis.skipBytes(dis.available()); // TODO 正常ファイルなら必要なし } /** */ @@ -128,15 +129,15 @@ boolean isUnicode(int languageCode) { class SubData { /** */ - SubData(InputStream is) throws IOException { + SubData(DataInput di) throws IOException { byte[] temp = new byte[2]; - read(is, temp); + di.readFully(temp); this.tag = new String(temp); - int size = readShort(is); + int size = di.readUnsignedShort(); this.data = new byte[size]; - read(is, this.data); + di.readFully(this.data); } /** */ @@ -181,7 +182,7 @@ public String toString() { if (printable) { return "SubData(" + new String(tag) + ", lang: " + getLanguageCode() + ", size: " + data.length + "): " + string; } else { - return "SubData(" + new String(tag) + ", lang: " + getLanguageCode() + ", size: " + data.length + ")\n" + StringUtil.getDump(data); + return "SubData(" + new String(tag) + ", lang: " + getLanguageCode() + ", size: " + data.length + ")\n" + StringUtil.getDump(data, 128); } } catch (UnsupportedEncodingException e) { assert false; diff --git a/src/main/java/vavi/sound/smaf/chunk/DisplayParameterDefinitionChunk.java b/src/main/java/vavi/sound/smaf/chunk/DisplayParameterDefinitionChunk.java index 10ff027..fd7d2d6 100644 --- a/src/main/java/vavi/sound/smaf/chunk/DisplayParameterDefinitionChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/DisplayParameterDefinitionChunk.java @@ -8,11 +8,11 @@ import java.io.DataOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; +import vavi.sound.midi.MidiUtil; import vavi.sound.smaf.InvalidSmafDataException; import vavi.util.Debug; @@ -40,19 +40,19 @@ public DisplayParameterDefinitionChunk() { } /** */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { int i = 0; while (i < size) { - int eventSize = readOneToTwo(is); - int eventType = read(is); + int eventSize = MidiUtil.readVariableLength(dis); + int eventType = dis.readUnsignedByte(); Event event = new Event(); event.eventType = eventType; Debug.println("event: " + eventType); for (int j = 0; j < ((eventSize - 1) / 2); j++) { - int parameterId = read(is); - int parameterValue = read(is); + int parameterId = dis.readUnsignedByte(); + int parameterValue = dis.readUnsignedByte(); Event.Parameter parameter = new Event.Parameter(); parameter.parameterID = ParameterID.valueOf(parameterId); parameter.value = parameterValue; diff --git a/src/main/java/vavi/sound/smaf/chunk/FileChunk.java b/src/main/java/vavi/sound/smaf/chunk/FileChunk.java index 74559d9..85812d2 100644 --- a/src/main/java/vavi/sound/smaf/chunk/FileChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/FileChunk.java @@ -9,7 +9,6 @@ import java.io.DataOutputStream; import java.io.FilterOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; @@ -41,11 +40,11 @@ public FileChunk() { } /** */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { - while (available() > 2) { - Chunk chunk = readFrom(is); + while (dis.available() > 2) { + Chunk chunk = readFrom(dis); if (chunk instanceof ContentsInfoChunk) { contentsInfoChunk = chunk; } else if (chunk instanceof OptionalDataChunk) { @@ -64,11 +63,11 @@ protected void init(InputStream is, Chunk parent) } } //Debug.println("available: " + is.available()); - this.crc = readShort(is); + this.crc = dis.readUnsignedShort(); Debug.printf("crc (orig): %04x\n", crc); - if (is.available() > 4) { - int kddiCrc = readShort(is); - int kddiMark = readShort(is); + if (dis.available() > 4) { + int kddiCrc = dis.readUnsignedShort(); + int kddiMark = dis.readUnsignedShort(); Debug.printf("has kddi crc: %04x, %04x\n", kddiCrc, kddiMark); } } diff --git a/src/main/java/vavi/sound/smaf/chunk/GraphicsSetupDataChunk.java b/src/main/java/vavi/sound/smaf/chunk/GraphicsSetupDataChunk.java index cdfa2d8..104c452 100644 --- a/src/main/java/vavi/sound/smaf/chunk/GraphicsSetupDataChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/GraphicsSetupDataChunk.java @@ -8,7 +8,6 @@ import java.io.DataOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.util.logging.Level; @@ -39,9 +38,9 @@ public GraphicsSetupDataChunk() { } /** */ - protected void init(InputStream is, Chunk parent) throws InvalidSmafDataException, IOException { - while (available() > 0) { - Chunk chunk = readFrom(is); + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { + while (dis.available() > 0) { + Chunk chunk = readFrom(dis); if (chunk instanceof DisplayParameterDefinitionChunk) { displayParameterDefinitionChunk = chunk; } else if (chunk instanceof ColorPaletteDefinitionChunk) { diff --git a/src/main/java/vavi/sound/smaf/chunk/GraphicsTrackChunk.java b/src/main/java/vavi/sound/smaf/chunk/GraphicsTrackChunk.java index 445d96f..d1256f3 100644 --- a/src/main/java/vavi/sound/smaf/chunk/GraphicsTrackChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/GraphicsTrackChunk.java @@ -8,7 +8,6 @@ import java.io.DataOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; @@ -16,7 +15,7 @@ import java.util.Map; import java.util.logging.Level; -import vavi.sound.midi.MidiConstants; +import vavi.sound.midi.MidiConstants.MetaEvent; import vavi.sound.smaf.InvalidSmafDataException; import vavi.sound.smaf.MetaMessage; import vavi.sound.smaf.SmafEvent; @@ -55,23 +54,23 @@ public GraphicsTrackChunk() { } /** */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { //skip(is, size); - this.formatType = FormatType.values()[read(is)]; + this.formatType = FormatType.values()[dis.readUnsignedByte()]; - this.playerType = read(is); - this.textEncodeType = read(is); - this.colorType = read(is); - this.durationTimeBase = read(is); + this.playerType = dis.readUnsignedByte(); + this.textEncodeType = dis.readUnsignedByte(); + this.colorType = dis.readUnsignedByte(); + this.durationTimeBase = dis.readUnsignedByte(); - int optionSize = read(is); + int optionSize = dis.readUnsignedByte(); this.optionData = new byte[optionSize]; - read(is, optionData); + dis.readFully(optionData); - while (available() > 0) { - Chunk chunk = readFrom(is); + while (dis.available() > 0) { + Chunk chunk = readFrom(dis); if (chunk instanceof GraphicsSetupDataChunk) { setupDataChunk = chunk; } else if (chunk instanceof GraphicsTrackSequenceDataChunk) { @@ -161,7 +160,7 @@ public List getSmafEvents() throws InvalidSmafDataException { props.put("timeBase", durationTimeBase); MetaMessage metaMessage = new MetaMessage(); - metaMessage.setMessage(MidiConstants.META_MACHINE_DEPEND, props); + metaMessage.setMessage(MetaEvent.META_MACHINE_DEPEND.number(), props); events.add(new SmafEvent(metaMessage, 0l)); return null; // TODO @@ -172,9 +171,9 @@ public static class FontDataChunk extends Chunk { // "Ge**” :Font Chunk // "Gu**” :Unicode Font Chunk /** */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { -skip(is, size); // TODO +dis.skipBytes((int) (long) size); // TODO } /** TODO */ diff --git a/src/main/java/vavi/sound/smaf/chunk/GraphicsTrackSequenceDataChunk.java b/src/main/java/vavi/sound/smaf/chunk/GraphicsTrackSequenceDataChunk.java index ec55e75..e9ca304 100644 --- a/src/main/java/vavi/sound/smaf/chunk/GraphicsTrackSequenceDataChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/GraphicsTrackSequenceDataChunk.java @@ -6,9 +6,10 @@ package vavi.sound.smaf.chunk; +import java.io.DataInputStream; import java.io.IOException; -import java.io.InputStream; +import vavi.sound.midi.MidiUtil; import vavi.sound.smaf.InvalidSmafDataException; import vavi.sound.smaf.SmafMessage; import vavi.sound.smaf.chunk.TrackChunk.FormatType; @@ -50,13 +51,13 @@ public GraphicsTrackSequenceDataChunk() { } /** */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { FormatType formatType = ((TrackChunk) parent).getFormatType(); switch (formatType) { case HandyPhoneStandard: - readHandyPhoneStandard(is); + readHandyPhoneStandard(dis); break; default: throw new InvalidSmafDataException("FormatType: " + formatType); @@ -65,17 +66,17 @@ protected void init(InputStream is, Chunk parent) } /** formatType 0 */ - protected void readHandyPhoneStandard(InputStream is) + protected void readHandyPhoneStandard(DataInputStream dis) throws InvalidSmafDataException, IOException { SmafMessage smafMessage = null; - while (available() > 0) { + while (dis.available() > 0) { // -------- duration -------- - int duration = readOneToTwo(is); + int duration = MidiUtil.readVariableLength(dis); //Debug.println("duration: " + duration + ", 0x" + StringUtil.toHex4(duration)); // -------- event -------- - int e1 = read(is); + int e1 = dis.readUnsignedByte(); switch (e1) { case 0x00: // short event smafMessage = new NopMessage(duration); @@ -84,33 +85,33 @@ protected void readHandyPhoneStandard(InputStream is) smafMessage = new ResetOrigneMessage(duration); break; case 0x20: { // control event - int size = readOneToTwo(is); + int size = MidiUtil.readVariableLength(dis); byte[] data = new byte[size]; - read(is, data); + dis.readFully(data); smafMessage = new BackDropColorDefinitionMessage(duration, data); } break; case 0x21: { // control event - int size = readOneToTwo(is); + int size = MidiUtil.readVariableLength(dis); byte[] data = new byte[size]; - read(is, data); + dis.readFully(data); smafMessage = new OffsetOriginMessage(duration, data); } break; case 0x22: { // control event - int size = readOneToTwo(is); + int size = MidiUtil.readVariableLength(dis); byte[] data = new byte[size]; - read(is, data); + dis.readFully(data); smafMessage = new UserMessage(duration, data); } break; case 0x40: { // display object event - int size = readOneToTwo(is); + int size = MidiUtil.readVariableLength(dis); byte[] data = new byte[size]; - read(is, data); + dis.readFully(data); smafMessage = new GeneralPurposeDisplayMessage(duration, e1, data); } break; default: { - int size = readOneToTwo(is); + int size = MidiUtil.readVariableLength(dis); byte[] data = new byte[size]; - read(is, data); + dis.readFully(data); smafMessage = new UndefinedMessage(duration); Debug.printf("reserved: %02x\n", e1); } break; diff --git a/src/main/java/vavi/sound/smaf/chunk/ImageChunk.java b/src/main/java/vavi/sound/smaf/chunk/ImageChunk.java index b18c6cc..7950ad0 100644 --- a/src/main/java/vavi/sound/smaf/chunk/ImageChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/ImageChunk.java @@ -9,7 +9,6 @@ import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import javax.imageio.ImageIO; @@ -46,11 +45,11 @@ public ImageChunk() { } /** */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { this.imageData = new byte[size]; - read(is, imageData); + dis.readFully(imageData); Debug.println("image: " + getImage()); } diff --git a/src/main/java/vavi/sound/smaf/chunk/ImageDataChunk.java b/src/main/java/vavi/sound/smaf/chunk/ImageDataChunk.java index 5c933d8..4fdac79 100644 --- a/src/main/java/vavi/sound/smaf/chunk/ImageDataChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/ImageDataChunk.java @@ -7,7 +7,6 @@ package vavi.sound.smaf.chunk; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; @@ -40,11 +39,11 @@ public ImageDataChunk() { } /** */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { - while (available() > 0) { - Chunk chunk = readFrom(is); + while (dis.available() > 0) { + Chunk chunk = readFrom(dis); if (chunk instanceof ImageChunk) { // "Gig*" imageDataChunks.add(chunk); } else if (chunk instanceof BitmapChunk) { // "" diff --git a/src/main/java/vavi/sound/smaf/chunk/LinkChunk.java b/src/main/java/vavi/sound/smaf/chunk/LinkChunk.java index 3a32a00..586dd9f 100644 --- a/src/main/java/vavi/sound/smaf/chunk/LinkChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/LinkChunk.java @@ -7,7 +7,6 @@ package vavi.sound.smaf.chunk; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import vavi.sound.smaf.InvalidSmafDataException; @@ -37,9 +36,9 @@ public LinkChunk() { } /** */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { -skip(is, size); // TODO +dis.skipBytes((int) (long) size); // TODO } /** TODO */ diff --git a/src/main/java/vavi/sound/smaf/chunk/MasterTrackChunk.java b/src/main/java/vavi/sound/smaf/chunk/MasterTrackChunk.java index 8d3bb7b..9db2794 100644 --- a/src/main/java/vavi/sound/smaf/chunk/MasterTrackChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/MasterTrackChunk.java @@ -7,7 +7,6 @@ package vavi.sound.smaf.chunk; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.util.List; import java.util.logging.Level; @@ -34,21 +33,21 @@ public MasterTrackChunk(byte[] id, int size) { } /** */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { - this.formatType = FormatType.values()[read(is)]; - this.sequenceType = SequenceType.values()[read(is)]; + this.formatType = FormatType.values()[dis.readUnsignedByte()]; + this.sequenceType = SequenceType.values()[dis.readUnsignedByte()]; Debug.println("sequenceType: " + sequenceType); - this.durationTimeBase = read(is); + this.durationTimeBase = dis.readUnsignedByte(); //Debug.println("durationTimeBase: " + StringUtil.toHex2(durationTimeBase)); - int optionSize = read(is); + int optionSize = dis.readUnsignedByte(); this.optionData = new byte[optionSize]; - read(is, optionData); + dis.readFully(optionData); - while (available() > 0) { + while (dis.available() > 0) { //Debug.println("available: " + is.available() + ", " + available()); - Chunk chunk = readFrom(is); + Chunk chunk = readFrom(dis); if (chunk instanceof MasterTrackSequenceDataChunk) { // "Mssq" sequenceDataChunk = chunk; } else { diff --git a/src/main/java/vavi/sound/smaf/chunk/MasterTrackSequenceDataChunk.java b/src/main/java/vavi/sound/smaf/chunk/MasterTrackSequenceDataChunk.java index 6546eb7..ee270dd 100644 --- a/src/main/java/vavi/sound/smaf/chunk/MasterTrackSequenceDataChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/MasterTrackSequenceDataChunk.java @@ -7,7 +7,6 @@ package vavi.sound.smaf.chunk; import java.io.IOException; -import java.io.InputStream; import vavi.sound.smaf.InvalidSmafDataException; import vavi.util.Debug; @@ -30,9 +29,9 @@ public MasterTrackSequenceDataChunk(byte[] id, int size) { } /** TODO how to get formatType from parent chunk ??? */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { -skip(is, size); // TODO +dis.skipBytes((int) (long) size); // TODO } } diff --git a/src/main/java/vavi/sound/smaf/chunk/OptionalDataChunk.java b/src/main/java/vavi/sound/smaf/chunk/OptionalDataChunk.java index fa02e8d..548c83c 100644 --- a/src/main/java/vavi/sound/smaf/chunk/OptionalDataChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/OptionalDataChunk.java @@ -8,7 +8,6 @@ import java.io.DataOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; @@ -40,11 +39,11 @@ public OptionalDataChunk() { } /** */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { - while (available() > 0) { - Chunk data = readFrom(is); + while (dis.available() > 0) { + Chunk data = readFrom(dis); // TODO "Pro*" dataChunks.add(data); } diff --git a/src/main/java/vavi/sound/smaf/chunk/PcmAudioTrackChunk.java b/src/main/java/vavi/sound/smaf/chunk/PcmAudioTrackChunk.java index de707d1..dfb64b1 100644 --- a/src/main/java/vavi/sound/smaf/chunk/PcmAudioTrackChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/PcmAudioTrackChunk.java @@ -8,7 +8,6 @@ import java.io.DataOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; @@ -16,7 +15,7 @@ import java.util.Map; import java.util.logging.Level; -import vavi.sound.midi.MidiConstants; +import vavi.sound.midi.MidiConstants.MetaEvent; import vavi.sound.smaf.InvalidSmafDataException; import vavi.sound.smaf.MetaMessage; import vavi.sound.smaf.SmafEvent; @@ -49,25 +48,25 @@ public PcmAudioTrackChunk() { } /** */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { //skip(is, size); - this.formatType = FormatType.values()[read(is)]; + this.formatType = FormatType.values()[dis.readUnsignedByte()]; Debug.println("formatType: " + formatType); - this.sequenceType = SequenceType.values()[read(is)]; + this.sequenceType = SequenceType.values()[dis.readUnsignedByte()]; Debug.println("sequenceType: " + sequenceType); - this.waveType = new WaveType(readShort(is)); + this.waveType = new WaveType(dis.readUnsignedShort()); Debug.println("waveType: " + waveType); - this.durationTimeBase = read(is); + this.durationTimeBase = dis.readUnsignedByte(); Debug.println("durationTimeBase: " + durationTimeBase + ", " + getDurationTimeBase() + " ms"); - this.gateTimeTimeBase = read(is); + this.gateTimeTimeBase = dis.readUnsignedByte(); Debug.println("gateTimeTimeBase: " + gateTimeTimeBase + ", " + getGateTimeTimeBase() + " ms"); - while (available() > 0) { - Chunk chunk = readFrom(is); + while (dis.available() > 0) { + Chunk chunk = readFrom(dis); if (chunk instanceof SeekAndPhraseInfoChunk) { seekAndPhraseInfoChunk = chunk; } else if (chunk instanceof AudioSequenceDataChunk) { @@ -164,7 +163,7 @@ public List getSmafEvents() throws InvalidSmafDataException { props.put("gateTimeTimeBase", timeBaseTable[gateTimeTimeBase]); MetaMessage metaMessage = new MetaMessage(); - metaMessage.setMessage(MidiConstants.META_MACHINE_DEPEND, props); + metaMessage.setMessage(MetaEvent.META_MACHINE_DEPEND.number(), props); events.add(new SmafEvent(metaMessage, 0l)); // diff --git a/src/main/java/vavi/sound/smaf/chunk/ScoreTrackChunk.java b/src/main/java/vavi/sound/smaf/chunk/ScoreTrackChunk.java index 30bcdf0..fb4f216 100644 --- a/src/main/java/vavi/sound/smaf/chunk/ScoreTrackChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/ScoreTrackChunk.java @@ -8,7 +8,6 @@ import java.io.DataOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; @@ -16,7 +15,7 @@ import java.util.Map; import java.util.logging.Level; -import vavi.sound.midi.MidiConstants; +import vavi.sound.midi.MidiConstants.MetaEvent; import vavi.sound.smaf.InvalidSmafDataException; import vavi.sound.smaf.MetaMessage; import vavi.sound.smaf.SmafEvent; @@ -57,21 +56,21 @@ public ScoreTrackChunk() { } /** */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { - this.formatType = FormatType.values()[read(is)]; - this.sequenceType = SequenceType.values()[read(is)]; + this.formatType = FormatType.values()[dis.readUnsignedByte()]; + this.sequenceType = SequenceType.values()[dis.readUnsignedByte()]; Debug.println("sequenceType: " + sequenceType); - this.durationTimeBase = read(is); + this.durationTimeBase = dis.readUnsignedByte(); Debug.println("durationTimeBase: " + durationTimeBase + ", " + getDurationTimeBase() + " ms"); - this.gateTimeTimeBase = read(is); + this.gateTimeTimeBase = dis.readUnsignedByte(); Debug.println("gateTimeTimeBase: " + gateTimeTimeBase + ", " + getGateTimeTimeBase() + " ms"); switch (formatType) { case HandyPhoneStandard: { byte[] buffer = new byte[2]; - read(is, buffer); + dis.readFully(buffer); //Debug.println(StringUtil.getDump(channelStatus)); this.channelStatuses = new ChannelStatus[4]; for (int i = 0; i < 4; i++) { @@ -82,7 +81,7 @@ protected void init(InputStream is, Chunk parent) case MobileStandard_Compress: case MobileStandard_NoCompress: { byte[] buffer = new byte[16]; - read(is, buffer); + dis.readFully(buffer); this.channelStatuses = new ChannelStatus[16]; for (int i = 0; i < 16; i++) { channelStatuses[i] = new ChannelStatus(i, (int) buffer[i]); @@ -91,15 +90,15 @@ protected void init(InputStream is, Chunk parent) } break; case Unknown3: { byte[] buffer = new byte[32]; - read(is, buffer); + dis.readFully(buffer); // TODO implement } break; } Debug.println("formatType: " + formatType); - while (available() > 0) { + while (dis.available() > 0) { //Debug.println("available: " + is.available() + ", " + available()); - Chunk chunk = readFrom(is); + Chunk chunk = readFrom(dis); if (chunk instanceof SeekAndPhraseInfoChunk) { seekAndPhraseInfoChunk = chunk; } else if (chunk instanceof SequenceDataChunk) { @@ -195,7 +194,7 @@ public List getSmafEvents() throws InvalidSmafDataException { props.put("gateTimeTimeBase", timeBaseTable[gateTimeTimeBase]); MetaMessage metaMessage = new MetaMessage(); - metaMessage.setMessage(MidiConstants.META_MACHINE_DEPEND, props); + metaMessage.setMessage(MetaEvent.META_MACHINE_DEPEND.number(), props); events.add(new SmafEvent(metaMessage, 0l)); // diff --git a/src/main/java/vavi/sound/smaf/chunk/SeekAndPhraseInfoChunk.java b/src/main/java/vavi/sound/smaf/chunk/SeekAndPhraseInfoChunk.java index 4ce95a9..9131c8e 100644 --- a/src/main/java/vavi/sound/smaf/chunk/SeekAndPhraseInfoChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/SeekAndPhraseInfoChunk.java @@ -8,7 +8,6 @@ import java.io.DataOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.util.List; @@ -42,12 +41,12 @@ public SeekAndPhraseInfoChunk() { } /** */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { byte[] data = new byte[size]; Debug.println("SeekAndPhraseInfo: " + size + " bytes (subData)"); - read(is, data); + dis.readFully(data); int i = 0; while (i < size) { diff --git a/src/main/java/vavi/sound/smaf/chunk/SequenceDataChunk.java b/src/main/java/vavi/sound/smaf/chunk/SequenceDataChunk.java index 08d1a62..541cc82 100644 --- a/src/main/java/vavi/sound/smaf/chunk/SequenceDataChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/SequenceDataChunk.java @@ -10,7 +10,6 @@ import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashSet; @@ -18,6 +17,7 @@ import java.util.Set; import java.util.logging.Level; +import vavi.sound.midi.MidiUtil; import vavi.sound.smaf.InvalidSmafDataException; import vavi.sound.smaf.SmafMessage; import vavi.sound.smaf.SysexMessage; @@ -62,19 +62,19 @@ public SequenceDataChunk() { } /** TODO how to get formatType from parent chunk ??? */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { //Debug.println("available: " + is.available() + ", " + available()); //skip(is, size); ScoreTrackChunk.FormatType formatType = ((TrackChunk) parent).getFormatType(); switch (formatType) { case HandyPhoneStandard: - readHandyPhoneStandard(is); + readHandyPhoneStandard(dis); break; case MobileStandard_Compress: ByteArrayOutputStream baos = new ByteArrayOutputStream(); for (int i = 0; i < size; i++) { - baos.write(is.read()); + baos.write(dis.read()); } //OutputStream os1 = new FileOutputStream("/tmp/data.enc"); //os1.write(baos.toByteArray()); @@ -89,11 +89,11 @@ protected void init(InputStream is, Chunk parent) //Debug.println("data.dec created"); Debug.println("decode: " + size + " -> " + decoded.length); size = decoded.length; - readMobileStandard(new ByteArrayInputStream(decoded)); + readMobileStandard(new MyDataInputStream(new ByteArrayInputStream(decoded), id, decoded.length)); break; case MobileStandard_NoCompress: case Unknown3: // TODO - readMobileStandard(is); + readMobileStandard(dis); break; } Debug.println("messages: " + messages.size()); @@ -109,24 +109,24 @@ protected SmafMessage getHandyPhoneStandardMessage(int duration, int data, int g } /** formatType 0 */ - protected void readHandyPhoneStandard(InputStream is) + protected void readHandyPhoneStandard(MyDataInputStream dis) throws InvalidSmafDataException, IOException { SmafMessage smafMessage = null; - while (available() > 0) { + while (dis.available() > 0) { // -------- duration -------- - int duration = readOneToTwo(is); + int duration = MidiUtil.readVariableLength(dis); //Debug.println("duration: " + duration + ", 0x" + StringUtil.toHex4(duration)); // -------- event -------- - int e1 = read(is); + int e1 = dis.readUnsignedByte(); if (e1 == 0xff) { // exclusive, nop - int e2 = read(is); + int e2 = dis.readUnsignedByte(); switch (e2) { case 0xf0: // exclusive - int messageSize = read(is); + int messageSize = dis.readUnsignedByte(); byte[] data = new byte[messageSize]; - read(is, data); + dis.readFully(data); // TODO end check 0xf7 smafMessage = SysexMessage.Factory.getSysexMessage(duration, data); break; @@ -139,13 +139,13 @@ protected void readHandyPhoneStandard(InputStream is) break; } } else if (e1 != 0x00) { // note - int gateTime = readOneToTwo(is); + int gateTime = MidiUtil.readVariableLength(dis); //Debug.println("gateTime: " + gateTime + ", 0x" + StringUtil.toHex4(gateTime)); smafMessage = getHandyPhoneStandardMessage(duration, e1, gateTime); } else { // e1 == 0x00 other event - int e2 = read(is); + int e2 = dis.readUnsignedByte(); if (e2 == 0x00) { - int e3 = read(is); + int e3 = dis.readUnsignedByte(); if (e3 == 0x00) { smafMessage = new EndOfSequenceMessage(duration); } else { @@ -158,7 +158,7 @@ protected void readHandyPhoneStandard(InputStream is) int data = e2 & 0x0f; switch (event) { case 3: - int value = read(is); + int value = dis.readUnsignedByte(); switch (data) { case 0: // program change - 0x00 ~ 0x7f smafMessage = new ProgramChangeMessage(duration, channel, value); @@ -224,37 +224,37 @@ protected void readHandyPhoneStandard(InputStream is) private int cc = 0; /** formatType 1, 2 */ - private void readMobileStandard(InputStream is) + private void readMobileStandard(MyDataInputStream dis) throws InvalidSmafDataException, IOException { SmafMessage smafMessage = null; - while (available() > 0) { + while (dis.available() > 0) { // duration - int duration = readOneToFour(is); + int duration = MidiUtil.readVariableLength(dis); //Debug.println("duration: " + duration); // event - int status = read(is); + int status = dis.readUnsignedByte(); if (status >= 0x80 && status <= 0x8f) { // note w/o velocity int channel = status & 0x0f; - int note = read(is); - int gateTime = readOneToFour(is); + int note = dis.readUnsignedByte(); + int gateTime = MidiUtil.readVariableLength(dis); smafMessage = new NoteMessage(duration, channel, note, gateTime); } else if (status >= 0x90 && status <= 0x9f) { // note w/ velocity int channel = status & 0x0f; - int note = read(is); - int velocity = read(is); - int gateTime = readOneToFour(is); + int note = dis.readUnsignedByte(); + int velocity = dis.readUnsignedByte(); + int gateTime = MidiUtil.readVariableLength(dis); smafMessage = new NoteMessage(duration, channel, note, gateTime, velocity); } else if (status >= 0xa0 && status <= 0xaf) { // reserved - int d1 = read(is); - int d2 = read(is); + int d1 = dis.readUnsignedByte(); + int d2 = dis.readUnsignedByte(); smafMessage = null; Debug.printf(Level.WARNING, "reserved: 0xa_: %02x%02x\n", d1, d2); } else if (status >= 0xb0 && status <= 0xbf) { // control change int channel = status & 0x0f; - int control = read(is); - int value = read(is); + int control = dis.readUnsignedByte(); + int value = dis.readUnsignedByte(); switch (control) { // TODO no specification case 0x00: // バンクセレクト MSB smafMessage = new BankSelectMessage(duration, channel, value, BankSelectMessage.Significant.Least); @@ -297,25 +297,25 @@ private void readMobileStandard(InputStream is) } } else if (status >= 0xc0 && status <= 0xcf) { // program change int channel = status & 0x0f; - int program = read(is); + int program = dis.readUnsignedByte(); smafMessage = new ProgramChangeMessage(duration, channel, program); } else if (status >= 0xd0 && status <= 0xdf) { // reserved - int d1 = read(is); + int d1 = dis.readUnsignedByte(); smafMessage = new UndefinedMessage(duration); Debug.printf(Level.WARNING, "reserved: 0xd_: %02x\n", d1); } else if (status >= 0xe0 && status <= 0xef) { // pitch vend message int channel = status & 0x0f; - int lsb = read(is); - int msb = read(is); + int lsb = dis.readUnsignedByte(); + int msb = dis.readUnsignedByte(); smafMessage = new PitchBendMessage(duration, channel, (msb << 7) | lsb); } else if (status == 0xff) { // eos, nop - int d1 = read(is); + int d1 = dis.readUnsignedByte(); switch (d1) { case 0x00: smafMessage = new NopMessage(duration); break; case 0x2f: - int d2 = read(is); // must be 0 + int d2 = dis.readUnsignedByte(); // must be 0 if (d2 != 0) { Debug.printf(Level.WARNING, "illegal state: %02x\n", d2); } @@ -327,9 +327,9 @@ private void readMobileStandard(InputStream is) break; } } else if (status == 0xf0) { // exclusive - int messageSize = readOneToFour(is); + int messageSize = MidiUtil.readVariableLength(dis); byte[] data = new byte[messageSize]; - read(is, data); + dis.readFully(data); // TODO end check 0xf7 smafMessage = SysexMessage.Factory.getSysexMessage(duration, data); } else if (status < 0x80) { // data diff --git a/src/main/java/vavi/sound/smaf/chunk/SetupDataChunk.java b/src/main/java/vavi/sound/smaf/chunk/SetupDataChunk.java index 2bd2361..5660f82 100644 --- a/src/main/java/vavi/sound/smaf/chunk/SetupDataChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/SetupDataChunk.java @@ -8,12 +8,12 @@ import java.io.DataOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; +import vavi.sound.midi.MidiUtil; import vavi.sound.smaf.InvalidSmafDataException; import vavi.sound.smaf.SmafMessage; import vavi.sound.smaf.SysexMessage; @@ -44,19 +44,19 @@ public SetupDataChunk() { } /** */ - protected void init(InputStream is, Chunk parent) throws InvalidSmafDataException, IOException { + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { ScoreTrackChunk.FormatType formatType = ((ScoreTrackChunk) parent).getFormatType(); switch (formatType) { case HandyPhoneStandard: - readHandyPhoneStandard(is); + readHandyPhoneStandard(dis); break; case MobileStandard_Compress: - readMobileStandard(is); // TODO Huffman + readMobileStandard(dis); // TODO Huffman break; case MobileStandard_NoCompress: case Unknown3: - readMobileStandard(is); + readMobileStandard(dis); break; } Debug.println("messages: " + messages.size()); @@ -73,20 +73,20 @@ protected void init(InputStream is, Chunk parent) throws InvalidSmafDataExceptio * *
    */ - private void readHandyPhoneStandard(InputStream is) throws InvalidSmafDataException, IOException { + private void readHandyPhoneStandard(MyDataInputStream dis) throws InvalidSmafDataException, IOException { SmafMessage smafMessage = null; - while (available() > 0) { + while (dis.available() > 0) { // -------- event -------- - int e1 = read(is); + int e1 = dis.readUnsignedByte(); if (e1 == 0xff) { // exclusive - int e2 = read(is); + int e2 = dis.readUnsignedByte(); switch (e2) { case 0xf0: - int messageSize = read(is); + int messageSize = dis.readUnsignedByte(); byte[] data = new byte[messageSize]; - read(is, data); + dis.readFully(data); // TODO end check 0xf7 smafMessage = SysexMessage.Factory.getSysexMessage(0, data); break; @@ -109,17 +109,17 @@ private void readHandyPhoneStandard(InputStream is) throws InvalidSmafDataExcept } /** formatType 1, 2 */ - private void readMobileStandard(InputStream is) throws InvalidSmafDataException, IOException { + private void readMobileStandard(MyDataInputStream dis) throws InvalidSmafDataException, IOException { SmafMessage smafMessage = null; - while (available() > 0) { + while (dis.available() > 0) { // event - int status = read(is); + int status = dis.readUnsignedByte(); if (status == 0xf0) { // exclusive - int messageSize = readOneToFour(is); + int messageSize = MidiUtil.readVariableLength(dis); byte[] data = new byte[messageSize]; - read(is, data); + dis.readFully(data); // TODO end check 0xf7 smafMessage = SysexMessage.Factory.getSysexMessage(0, data); } else { diff --git a/src/main/java/vavi/sound/smaf/chunk/StreamPcmDataChunk.java b/src/main/java/vavi/sound/smaf/chunk/StreamPcmDataChunk.java index bee7337..2402112 100644 --- a/src/main/java/vavi/sound/smaf/chunk/StreamPcmDataChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/StreamPcmDataChunk.java @@ -8,7 +8,6 @@ import java.io.DataOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; @@ -43,9 +42,9 @@ public StreamPcmDataChunk() { } /** */ - protected void init(InputStream is, Chunk parent) throws InvalidSmafDataException, IOException { - while (available() > 0) { - Chunk chunk = readFrom(is); + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { + while (dis.available() > 0) { + Chunk chunk = readFrom(dis); if (chunk instanceof StreamWaveDataChunk) { streamWaveDataChunks.add(chunk); } else { diff --git a/src/main/java/vavi/sound/smaf/chunk/StreamWaveDataChunk.java b/src/main/java/vavi/sound/smaf/chunk/StreamWaveDataChunk.java index ad534e1..35a76cd 100644 --- a/src/main/java/vavi/sound/smaf/chunk/StreamWaveDataChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/StreamWaveDataChunk.java @@ -7,7 +7,6 @@ package vavi.sound.smaf.chunk; import java.io.IOException; -import java.io.InputStream; import vavi.sound.smaf.InvalidSmafDataException; import vavi.sound.smaf.SmafMessage; @@ -38,13 +37,13 @@ public StreamWaveDataChunk() { } /** */ - protected void init(InputStream is, Chunk parent) throws InvalidSmafDataException, IOException { + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { byte[] weveTypeBytes = new byte[3]; - read(is, weveTypeBytes); + dis.readFully(weveTypeBytes); this.waveType = new WaveType(weveTypeBytes); - data = new byte[available()]; - read(is, data); + data = new byte[dis.available()]; + dis.readFully(data); } /** */ diff --git a/src/main/java/vavi/sound/smaf/chunk/UndefinedChunk.java b/src/main/java/vavi/sound/smaf/chunk/UndefinedChunk.java index dd10974..22c275e 100644 --- a/src/main/java/vavi/sound/smaf/chunk/UndefinedChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/UndefinedChunk.java @@ -7,7 +7,6 @@ package vavi.sound.smaf.chunk; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.util.logging.Level; @@ -31,17 +30,23 @@ public UndefinedChunk(byte[] id, int size) { } /** */ - protected void init(InputStream is, Chunk parent) + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { + if (size > dis.available()) { +Debug.println(Level.WARNING, "read size is larger than available stream"); +//new Exception("*** DUMMY ***").printStackTrace(System.err); + throw new InvalidSmafDataException("read size is larger than available stream"); + } byte[] data = new byte[size]; - read(is, data); + dis.readFully(data); Debug.println(Level.WARNING, "Undefined: size: " + size + "\n" + StringUtil.getDump(data, 64)); } /** */ public void writeTo(OutputStream os) throws IOException { // TODO +Debug.println(Level.WARNING, "not implemented skip"); } } diff --git a/src/main/java/vavi/sound/smaf/chunk/WaveDataChunk.java b/src/main/java/vavi/sound/smaf/chunk/WaveDataChunk.java index d84ddea..4721235 100644 --- a/src/main/java/vavi/sound/smaf/chunk/WaveDataChunk.java +++ b/src/main/java/vavi/sound/smaf/chunk/WaveDataChunk.java @@ -8,7 +8,6 @@ import java.io.DataOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import vavi.sound.smaf.InvalidSmafDataException; @@ -42,9 +41,9 @@ public WaveDataChunk() { } /** */ - protected void init(InputStream is, Chunk parent) throws InvalidSmafDataException, IOException { + protected void init(MyDataInputStream dis, Chunk parent) throws InvalidSmafDataException, IOException { data = new byte[size]; - read(is, data); + dis.readFully(data); } /** */ diff --git a/src/main/java/vavi/sound/smaf/chunk/package.html b/src/main/java/vavi/sound/smaf/chunk/readme.md similarity index 64% rename from src/main/java/vavi/sound/smaf/chunk/package.html rename to src/main/java/vavi/sound/smaf/chunk/readme.md index 79b25d8..a053586 100644 --- a/src/main/java/vavi/sound/smaf/chunk/package.html +++ b/src/main/java/vavi/sound/smaf/chunk/readme.md @@ -1,36 +1,14 @@ - - +# vavi.sound.smaf.chunk - - - - - - -vavi.sound.smaf.chunk - - - - - -

    SMAF サウンド関連のファイル構造を表すクラスを提供します. -

    -

    概要

    +## Abstract + SMAF ファイルの読み込み時に使用されます。 -

    構造

    +## Structure -
    +```
                                                                             wav2mld
     
             FileChunk                                   (MMMD)              *
    @@ -55,14 +33,6 @@ 

    構造

    [MasterTrackChunk] (MSTR) crc * -
    - -

    これから実装すること

    - -
      -
    • -
    - - +``` - +## TODO diff --git a/src/main/java/vavi/sound/smaf/message/EndOfSequenceMessage.java b/src/main/java/vavi/sound/smaf/message/EndOfSequenceMessage.java index 7d85a33..4a71e84 100644 --- a/src/main/java/vavi/sound/smaf/message/EndOfSequenceMessage.java +++ b/src/main/java/vavi/sound/smaf/message/EndOfSequenceMessage.java @@ -7,10 +7,12 @@ package vavi.sound.smaf.message; import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; import java.io.IOException; import javax.sound.midi.MidiEvent; +import vavi.sound.midi.MidiUtil; import vavi.sound.smaf.SmafEvent; import vavi.sound.smaf.chunk.TrackChunk.FormatType; import vavi.util.Debug; @@ -54,7 +56,7 @@ public byte[] getMessage() { switch (formatType) { case HandyPhoneStandard: try { - writeOneToTwo(baos, duration); + MidiUtil.writeVarInt(new DataOutputStream(baos), duration); } catch (IOException e) { assert false; } diff --git a/src/main/java/vavi/sound/smaf/message/MidiContext.java b/src/main/java/vavi/sound/smaf/message/MidiContext.java index e756440..db8d547 100644 --- a/src/main/java/vavi/sound/smaf/message/MidiContext.java +++ b/src/main/java/vavi/sound/smaf/message/MidiContext.java @@ -10,7 +10,7 @@ import javax.sound.midi.MetaMessage; import javax.sound.midi.MidiEvent; -import vavi.sound.midi.MidiConstants; +import vavi.sound.midi.MidiConstants.MetaEvent; import vavi.sound.smaf.InvalidSmafDataException; import vavi.sound.smaf.SmafEvent; import vavi.sound.smaf.SmafMessage; @@ -69,7 +69,7 @@ public void setTrack(Track smafTrack) { SmafMessage message = event.getMessage(); if (message instanceof vavi.sound.smaf.MetaMessage) { vavi.sound.smaf.MetaMessage metaMessage = (vavi.sound.smaf.MetaMessage) message; - if (metaMessage.getType() == MidiConstants.META_MACHINE_DEPEND) { + if (metaMessage.getType() == MetaEvent.META_MACHINE_DEPEND.number()) { // this.formatType = (FormatType) metaMessage.getData().get("formatType"); // [ms] Debug.println("formatType: " + formatType); @@ -537,7 +537,7 @@ public int getResolution(Track[] smafTracks) SmafMessage message = event.getMessage(); if (message instanceof vavi.sound.smaf.MetaMessage) { vavi.sound.smaf.MetaMessage metaMessage = (vavi.sound.smaf.MetaMessage) message; - if (metaMessage.getType() == MidiConstants.META_MACHINE_DEPEND) { + if (metaMessage.getType() == MetaEvent.META_MACHINE_DEPEND.number()) { this.timeBase = (Integer) metaMessage.getData().get("durationTimeBase"); // [ms] Debug.println("timebase: " + timeBase + ", (" + t + ":" + i + ")"); return tempo * timeBase; diff --git a/src/main/java/vavi/sound/smaf/message/NopMessage.java b/src/main/java/vavi/sound/smaf/message/NopMessage.java index 7511ec3..06aa7af 100644 --- a/src/main/java/vavi/sound/smaf/message/NopMessage.java +++ b/src/main/java/vavi/sound/smaf/message/NopMessage.java @@ -7,10 +7,12 @@ package vavi.sound.smaf.message; import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; import java.io.IOException; import javax.sound.midi.MidiEvent; +import vavi.sound.midi.MidiUtil; import vavi.sound.smaf.ShortMessage; import vavi.sound.smaf.chunk.TrackChunk.FormatType; @@ -55,7 +57,7 @@ public byte[] getMessage() { switch (formatType) { case HandyPhoneStandard: try { - writeOneToTwo(baos, duration); + MidiUtil.writeVarInt(new DataOutputStream(baos), duration); } catch (IOException e) { assert false; } diff --git a/src/main/java/vavi/sound/smaf/message/STMessage.java b/src/main/java/vavi/sound/smaf/message/STMessage.java index 15b2415..ce3b67f 100644 --- a/src/main/java/vavi/sound/smaf/message/STMessage.java +++ b/src/main/java/vavi/sound/smaf/message/STMessage.java @@ -12,7 +12,7 @@ import javax.sound.midi.MetaMessage; import javax.sound.midi.MidiEvent; -import vavi.sound.midi.MidiConstants; +import vavi.sound.midi.MidiConstants.MetaEvent; import vavi.sound.smaf.SmafMessage; import vavi.util.Debug; @@ -80,7 +80,7 @@ public MidiEvent[] getMidiEvents(MidiContext context) throws InvalidMidiDataExce data = songTitle.getBytes(); } MetaMessage metaMessage = new MetaMessage(); - metaMessage.setMessage(MidiConstants.META_NAME, + metaMessage.setMessage(MetaEvent.META_NAME.number(), data, data.length); return new MidiEvent[] { diff --git a/src/main/java/vavi/sound/smaf/message/VNMessage.java b/src/main/java/vavi/sound/smaf/message/VNMessage.java index f2d845c..e0c4216 100644 --- a/src/main/java/vavi/sound/smaf/message/VNMessage.java +++ b/src/main/java/vavi/sound/smaf/message/VNMessage.java @@ -12,7 +12,7 @@ import javax.sound.midi.MetaMessage; import javax.sound.midi.MidiEvent; -import vavi.sound.midi.MidiConstants; +import vavi.sound.midi.MidiConstants.MetaEvent; import vavi.sound.smaf.SmafMessage; import vavi.util.Debug; @@ -80,7 +80,7 @@ public MidiEvent[] getMidiEvents(MidiContext context) throws InvalidMidiDataExce data = venderName.getBytes(); } MetaMessage metaMessage = new MetaMessage(); - metaMessage.setMessage(MidiConstants.META_TEXT_EVENT, + metaMessage.setMessage(MetaEvent.META_TEXT_EVENT.number(), data, data.length); return new MidiEvent[] { diff --git a/src/main/java/vavi/sound/smaf/message/VolumeMessage.java b/src/main/java/vavi/sound/smaf/message/VolumeMessage.java index 734b24e..8244a30 100644 --- a/src/main/java/vavi/sound/smaf/message/VolumeMessage.java +++ b/src/main/java/vavi/sound/smaf/message/VolumeMessage.java @@ -7,12 +7,14 @@ package vavi.sound.smaf.message; import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; import java.io.IOException; import javax.sound.midi.InvalidMidiDataException; import javax.sound.midi.MidiEvent; import javax.sound.midi.ShortMessage; +import vavi.sound.midi.MidiUtil; import vavi.sound.smaf.InvalidSmafDataException; import vavi.sound.smaf.SmafEvent; import vavi.sound.smaf.chunk.TrackChunk.FormatType; @@ -93,7 +95,7 @@ public byte[] getMessage() { switch (formatType) { case HandyPhoneStandard: try { - writeOneToTwo(baos, duration); + MidiUtil.writeVarInt(new DataOutputStream(baos), duration); } catch (IOException e) { assert false; } diff --git a/src/main/java/vavi/sound/smaf/message/WaveMessage.java b/src/main/java/vavi/sound/smaf/message/WaveMessage.java index 35dc56e..4de195f 100644 --- a/src/main/java/vavi/sound/smaf/message/WaveMessage.java +++ b/src/main/java/vavi/sound/smaf/message/WaveMessage.java @@ -7,6 +7,7 @@ package vavi.sound.smaf.message; import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; import java.io.IOException; import java.io.Serializable; @@ -14,6 +15,7 @@ import javax.sound.midi.MetaMessage; import javax.sound.midi.MidiEvent; +import vavi.sound.midi.MidiUtil; import vavi.sound.midi.VaviMidiDeviceProvider; import vavi.sound.mobile.AudioEngine; import vavi.sound.smaf.InvalidSmafDataException; @@ -116,7 +118,7 @@ public byte[] getMessage() { switch (formatType) { case HandyPhoneStandard: try { - writeOneToTwo(baos, duration); + MidiUtil.writeVarInt(new DataOutputStream(baos), duration); } catch (IOException e) { assert false; } @@ -125,7 +127,7 @@ public byte[] getMessage() { event |= number & 0x3f; baos.write(event); try { - writeOneToTwo(baos, gateTime); + MidiUtil.writeVarInt(new DataOutputStream(baos), gateTime); } catch (IOException e) { assert false; } diff --git a/src/main/java/vavi/sound/smaf/message/graphics/BackDropColorDefinitionMessage.java b/src/main/java/vavi/sound/smaf/message/graphics/BackDropColorDefinitionMessage.java index 92dbe7b..b86070f 100644 --- a/src/main/java/vavi/sound/smaf/message/graphics/BackDropColorDefinitionMessage.java +++ b/src/main/java/vavi/sound/smaf/message/graphics/BackDropColorDefinitionMessage.java @@ -7,8 +7,10 @@ package vavi.sound.smaf.message.graphics; import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; import java.io.IOException; +import vavi.sound.midi.MidiUtil; import vavi.sound.smaf.ShortMessage; import vavi.sound.smaf.chunk.TrackChunk.FormatType; @@ -55,7 +57,7 @@ public byte[] getMessage() { switch (formatType) { case HandyPhoneStandard: try { - writeOneToTwo(baos, duration); + MidiUtil.writeVarInt(new DataOutputStream(baos), duration); } catch (IOException e) { assert false; } diff --git a/src/main/java/vavi/sound/smaf/message/graphics/GeneralPurposeDisplayMessage.java b/src/main/java/vavi/sound/smaf/message/graphics/GeneralPurposeDisplayMessage.java index 41365ca..3281c10 100644 --- a/src/main/java/vavi/sound/smaf/message/graphics/GeneralPurposeDisplayMessage.java +++ b/src/main/java/vavi/sound/smaf/message/graphics/GeneralPurposeDisplayMessage.java @@ -7,8 +7,10 @@ package vavi.sound.smaf.message.graphics; import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; import java.io.IOException; +import vavi.sound.midi.MidiUtil; import vavi.sound.smaf.ShortMessage; import vavi.sound.smaf.chunk.TrackChunk.FormatType; @@ -71,12 +73,13 @@ public byte[] getMessage() { switch (formatType) { case HandyPhoneStandard: try { - writeOneToTwo(baos, duration); + DataOutputStream dos = new DataOutputStream(baos); + MidiUtil.writeVarInt(dos, duration); baos.write(eventType); - writeOneToTwo(baos, 0); // TODO size - writeOneToTwo(baos, lifeTime); - writeOneToTwo(baos, coordinates); - writeOneToTwo(baos, subBlocks); + MidiUtil.writeVarInt(dos, 0); // TODO size + MidiUtil.writeVarInt(dos, lifeTime); + MidiUtil.writeVarInt(dos, coordinates); + MidiUtil.writeVarInt(dos, subBlocks); } catch (IOException e) { assert false; } diff --git a/src/main/java/vavi/sound/smaf/message/graphics/NopMessage.java b/src/main/java/vavi/sound/smaf/message/graphics/NopMessage.java index 7bb36bb..8163a14 100644 --- a/src/main/java/vavi/sound/smaf/message/graphics/NopMessage.java +++ b/src/main/java/vavi/sound/smaf/message/graphics/NopMessage.java @@ -7,8 +7,10 @@ package vavi.sound.smaf.message.graphics; import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; import java.io.IOException; +import vavi.sound.midi.MidiUtil; import vavi.sound.smaf.ShortMessage; import vavi.sound.smaf.chunk.TrackChunk.FormatType; @@ -49,7 +51,7 @@ public byte[] getMessage() { switch (formatType) { case HandyPhoneStandard: try { - writeOneToTwo(baos, duration); + MidiUtil.writeVarInt(new DataOutputStream(baos), duration); } catch (IOException e) { assert false; } diff --git a/src/main/java/vavi/sound/smaf/message/graphics/OffsetOriginMessage.java b/src/main/java/vavi/sound/smaf/message/graphics/OffsetOriginMessage.java index 8cf9475..ccda283 100644 --- a/src/main/java/vavi/sound/smaf/message/graphics/OffsetOriginMessage.java +++ b/src/main/java/vavi/sound/smaf/message/graphics/OffsetOriginMessage.java @@ -7,8 +7,10 @@ package vavi.sound.smaf.message.graphics; import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; import java.io.IOException; +import vavi.sound.midi.MidiUtil; import vavi.sound.smaf.ShortMessage; import vavi.sound.smaf.chunk.TrackChunk.FormatType; @@ -51,7 +53,7 @@ public byte[] getMessage() { switch (formatType) { case HandyPhoneStandard: try { - writeOneToTwo(baos, duration); + MidiUtil.writeVarInt(new DataOutputStream(baos), duration); } catch (IOException e) { assert false; } diff --git a/src/main/java/vavi/sound/smaf/message/graphics/ResetOrigneMessage.java b/src/main/java/vavi/sound/smaf/message/graphics/ResetOrigneMessage.java index 74ba6f6..81ef9b9 100644 --- a/src/main/java/vavi/sound/smaf/message/graphics/ResetOrigneMessage.java +++ b/src/main/java/vavi/sound/smaf/message/graphics/ResetOrigneMessage.java @@ -7,8 +7,10 @@ package vavi.sound.smaf.message.graphics; import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; import java.io.IOException; +import vavi.sound.midi.MidiUtil; import vavi.sound.smaf.ShortMessage; import vavi.sound.smaf.chunk.TrackChunk.FormatType; @@ -48,7 +50,7 @@ public byte[] getMessage() { switch (formatType) { case HandyPhoneStandard: try { - writeOneToTwo(baos, duration); + MidiUtil.writeVarInt(new DataOutputStream(baos), duration); } catch (IOException e) { assert false; } diff --git a/src/main/java/vavi/sound/smaf/message/graphics/UserMessage.java b/src/main/java/vavi/sound/smaf/message/graphics/UserMessage.java index d4597cf..f8c7b64 100644 --- a/src/main/java/vavi/sound/smaf/message/graphics/UserMessage.java +++ b/src/main/java/vavi/sound/smaf/message/graphics/UserMessage.java @@ -7,8 +7,10 @@ package vavi.sound.smaf.message.graphics; import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; import java.io.IOException; +import vavi.sound.midi.MidiUtil; import vavi.sound.smaf.ShortMessage; import vavi.sound.smaf.chunk.TrackChunk.FormatType; @@ -56,7 +58,7 @@ public byte[] getMessage() { switch (formatType) { case HandyPhoneStandard: try { - writeOneToTwo(baos, duration); + MidiUtil.writeVarInt(new DataOutputStream(baos), duration); } catch (IOException e) { assert false; } diff --git a/src/main/java/vavi/sound/smaf/package.html b/src/main/java/vavi/sound/smaf/package.html deleted file mode 100644 index 15283f1..0000000 --- a/src/main/java/vavi/sound/smaf/package.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - -vavi.sound.smaf - - - - - -

    -SMAF サウンド関連のクラスを提供します. -

    - -

    概要

    -{@link javax.sound.midi} パッケージとほぼ同じ構造をしています。 -使用法は {@link javax.sound.midi} を参考にしてください。 - -

    これから実装すること

    - -
      -
    • smaf -> midi がおかしい
    • -
    • ma# emu を使用したシーケンサーとか mmftool
    • -
    • HV と VSQ の相互変換?
    • -
    • GraphicsTrackChunk でモバラジ
    • -
    • gervill
    • -
    - -

    参考

    -

    -

    -MMFplay -

    - -

    - - - diff --git a/src/main/java/vavi/sound/smaf/readme.md b/src/main/java/vavi/sound/smaf/readme.md new file mode 100644 index 0000000..98498c7 --- /dev/null +++ b/src/main/java/vavi/sound/smaf/readme.md @@ -0,0 +1,20 @@ +# vavi.sound.smaf + +SMAF サウンド関連のクラスを提供します. + +## Abstract + +{@link javax.sound.midi} パッケージとほぼ同じ構造をしています。 +使用法は {@link javax.sound.midi} を参考にしてください。 + +## TODO + + * ~~ datetime="080512" smaf -> midi がおかしい~~ + * ma# emu を使用したシーケンサーとか [mmftool](https://murachue.sytes.net/web/softlist.cgi?mode=desc&title=mmftool) + * HV と VSQ の相互変換? + * GraphicsTrackChunk でモバラジ + * gervill + +## Reference + + * [MMFplay](http://mmfplay.sourceforge.net/) diff --git a/src/main/java/vavi/sound/smaf/sequencer/WaveSequencer.java b/src/main/java/vavi/sound/smaf/sequencer/WaveSequencer.java index 04aaf3a..ebbe910 100644 --- a/src/main/java/vavi/sound/smaf/sequencer/WaveSequencer.java +++ b/src/main/java/vavi/sound/smaf/sequencer/WaveSequencer.java @@ -13,6 +13,10 @@ /** * WaveSequencer. + *
    + * properties file ... "/vavi/sound/smaf/smaf.properties"
    + * name prefix ... "audioEngine.format."
    + * 
    * * @author Naohide Sano (nsano) * @version 0.00 071010 nsano initial version
    @@ -25,7 +29,7 @@ public interface WaveSequencer { /** */ void sequence() throws InvalidSmafDataException; - /** */ + /** factory */ class Factory extends PrefixedClassPropertiesFactory { /** */ diff --git a/src/main/java/vavi/util/package.html b/src/main/java/vavi/util/package.html deleted file mode 100644 index c7c8e12..0000000 --- a/src/main/java/vavi/util/package.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - -vavi.util - - - - - -

    -FFT, Bessel 関連のクラスを提供します. -

    - -

    これから実装すること

    - -
      -
    • FFT がおかしい
    • -
    • FFT がバージョンアップしてる
    • -
    - -

    一次ライセンス

    - -

    SplitRasixFft

    - -
    -    Copyright(C) 1996-2001 Takuya OOURA
    -    email: ooura@mmm.t.u-tokyo.ac.jp
    -    download: http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html
    -    You may use, copy, modify this code for any purpose and 
    -    without fee. You may distribute this ORIGINAL package.
    -
    - -

    I0Bessel

    - -
    -    Copyright(C) 1996 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp).
    -    You may use, copy, modify this code for any purpose and 
    -    without fee. You may distribute this ORIGINAL package.
    -
    - - - diff --git a/src/main/java/vavi/util/readme.md b/src/main/java/vavi/util/readme.md new file mode 100644 index 0000000..a7acaa9 --- /dev/null +++ b/src/main/java/vavi/util/readme.md @@ -0,0 +1,28 @@ +# vavi.util + +FFT, Bessel 関連のクラスを提供します. + +## TODO + + * ~~FFT がおかしい~~ + * FFT がバージョンアップしてる + +## License + +### SplitRasixFft + +``` + Copyright(C) 1996-2001 Takuya OOURA + email: ooura@mmm.t.u-tokyo.ac.jp + download: http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html + You may use, copy, modify this code for any purpose and + without fee. You may distribute this ORIGINAL package. +``` + +### I0Bessel + +``` + Copyright(C) 1996 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp). + You may use, copy, modify this code for any purpose and + without fee. You may distribute this ORIGINAL package. +``` \ No newline at end of file diff --git a/src/main/resources/vavi/sound/mfi/MfiSystem.properties b/src/main/resources/vavi/sound/mfi/MfiSystem.properties index 1da94e9..e075858 100644 --- a/src/main/resources/vavi/sound/mfi/MfiSystem.properties +++ b/src/main/resources/vavi/sound/mfi/MfiSystem.properties @@ -10,10 +10,10 @@ # ## -# MfiSystem ftHgŎgp MfiDeviceProvider +# MfiSystem がデフォルトで使用する MfiDeviceProvider # -# @name "default.provider" L[ -# @value MfiDeviceProvider NX +# @name "default.provider" キー +# @value MfiDeviceProvider クラス名 # @see vavi.sound.mfi.MfiSystem # #default.provider=vavi.sound.mfi.ittake.IttakeMfiDeviceProvider diff --git a/src/main/resources/vavi/sound/mfi/vavi/mitsubishi/mitsubishi.properties b/src/main/resources/vavi/sound/mfi/vavi/mitsubishi/mitsubishi.properties index c581226..35d715f 100644 --- a/src/main/resources/vavi/sound/mfi/vavi/mitsubishi/mitsubishi.properties +++ b/src/main/resources/vavi/sound/mfi/vavi/mitsubishi/mitsubishi.properties @@ -11,21 +11,21 @@ # # MitsubishiSequencer # -# 0x01 Pitch Bend ݒ +# 0x01 Pitch Bend 設定 function.1=vavi.sound.mfi.vavi.mitsubishi.Function1 -# 0x02 Pitch Bend Range ݒ +# 0x02 Pitch Bend Range 設定 function.2=vavi.sound.mfi.vavi.mitsubishi.Function2 -# 0x03 Modulation ݒ +# 0x03 Modulation 設定 function.3=vavi.sound.mfi.vavi.mitsubishi.Function3 -# 0x10 UCS Wave ݒ +# 0x10 UCS Wave 設定 #function.16=vavi.sound.mfi.vavi.mitsubishi.Function16 -# 0x11 UCS Parameter ݒ +# 0x11 UCS Parameter 設定 #function.17=vavi.sound.mfi.vavi.mitsubishi.Function17 -# 0x12 UCS ǗXe[^Xݒ +# 0x12 UCS 管理ステータス設定 #function.18=vavi.sound.mfi.vavi.mitsubishi.Function18 -# 0x81 WAVE Channel Volume ݒ +# 0x81 WAVE Channel Volume 設定 function.129=vavi.sound.mfi.vavi.mitsubishi.Function129 -# 0x82 WAVE Channel Panpot ݒ +# 0x82 WAVE Channel Panpot 設定 function.130=vavi.sound.mfi.vavi.mitsubishi.Function130 # 0x83 WAVE Packet Data function.131=vavi.sound.mfi.vavi.mitsubishi.Function131 diff --git a/src/main/resources/vavi/sound/mfi/vavi/nec/nec.properties b/src/main/resources/vavi/sound/mfi/vavi/nec/nec.properties index 5dbb9f6..9b58a9f 100644 --- a/src/main/resources/vavi/sound/mfi/vavi/nec/nec.properties +++ b/src/main/resources/vavi/sound/mfi/vavi/nec/nec.properties @@ -28,13 +28,13 @@ function.242.4=vavi.sound.mfi.vavi.nec.Function242_4 # f2._5 LED function.242.5=vavi.sound.mfi.vavi.nec.Function242_5 -# 01.f0._3 g FM {g` -# 01.f0._4 g FM Fw -# 01.f0._5 g WT Fw -# 01.f0._6 g WT g`w -# 01.f0._7 gXg[g` +# 01.f0._3 拡張 FM 基本波形 +# 01.f0._4 拡張 FM 音色指定 +# 01.f0._5 拡張 WT 音色指定 +# 01.f0._6 拡張 WT 波形指定 +# 01.f0._7 拡張ストリーム波形制御情報 function.1.240.7=vavi.sound.mfi.vavi.nec.Function1_240_7 -# 01.f0._8 g AL Fw +# 01.f0._8 拡張 AL 音色指定 # 01.f1.x3 StreamOn function.1.241.3=vavi.sound.mfi.vavi.nec.Function1_241_3 @@ -47,18 +47,18 @@ function.1.241.6=vavi.sound.mfi.vavi.nec.Function1_241_6 # 01.f1.x7 Hold1 # 01.f1.x8 MonoOn # 01.f1.x9 PlayOn -# 01.f1.xa tB^]iX -# 01.f1.xb tB^uCglX +# 01.f1.xa フィルタレゾナンス +# 01.f1.xb フィルタブライトネス -# 01.f2._7 Channel Status +# 01.f2._7 Channel Status 制御情報 -# 01.f3._1 FM [hݒ +# 01.f3._1 FM モード設定 # # 01.f3._2 UserEvent -# 01.f3._3 MaxGain ݒ +# 01.f3._3 MaxGain 設定 function.1.243.3=vavi.sound.mfi.vavi.nec.Function1_243_3 -# 01.f3._4 Xg[w +# 01.f3._4 ストリーム数指定 function.1.243.4=vavi.sound.mfi.vavi.nec.Function1_243_4 -# 01.f3._5 AL `lw +# 01.f3._5 AL チャンネル指定 ## diff --git a/src/main/resources/vavi/sound/mfi/vavi/sharp/sharp.properties b/src/main/resources/vavi/sound/mfi/vavi/sharp/sharp.properties index 50eaf9f..a44cd0f 100644 --- a/src/main/resources/vavi/sound/mfi/vavi/sharp/sharp.properties +++ b/src/main/resources/vavi/sound/mfi/vavi/sharp/sharp.properties @@ -11,9 +11,9 @@ # # SharpSequencer # -# 0x81 Wave Channel Volume ݒ +# 0x81 Wave Channel Volume 設定 function.129=vavi.sound.mfi.vavi.sharp.Function129 -# 0x82 Wave Channel Panpot ݒ +# 0x82 Wave Channel Panpot 設定 function.130=vavi.sound.mfi.vavi.sharp.Function130 # 0x83 Wave Packet Data function.131=vavi.sound.mfi.vavi.sharp.Function131 diff --git a/src/main/resources/vavi/sound/mfi/vavi/vavi.properties b/src/main/resources/vavi/sound/mfi/vavi/vavi.properties index c271a15..3c6d07c 100644 --- a/src/main/resources/vavi/sound/mfi/vavi/vavi.properties +++ b/src/main/resources/vavi/sound/mfi/vavi/vavi.properties @@ -13,7 +13,7 @@ #------------------------------------------------------------------------------ ## -# tH[}bg̃ftHg̒l +# フォーマットのデフォルトの値 # format.type.major=1 format.type.minor=1 @@ -24,9 +24,9 @@ format.header.vers=0400 #------------------------------------------------------------------------------ ## -# x_[ԍɑΉV[PT[ +# ベンダー番号に対応するシーケンサー # -# @name "sequencer.vendor" + x_[ԍ + LAԍ +# @name "sequencer.vendor" + ベンダー番号 + キャリア番号 # @see vavi.sound.mfi.vavi.MetaEventAdapter # # nec 16 | docomo 1 @@ -49,9 +49,9 @@ sequencer.vendor.113=vavi.sound.mfi.vavi.sharp.SharpSequencer #------------------------------------------------------------------------------ ## -# tH[}bg^CvɑΉ AudioEngine +# フォーマットタイプに対応する AudioEngine # -# @name "audioEngine.format" + tH[}bg^Cv +# @name "audioEngine.format" + フォーマットタイプ # @see vavi.sound.mobile.AudioDataMessage # # ADPCM Type1 0x80 ??? @@ -69,10 +69,10 @@ audioEngine.format.129=vavi.sound.mobile.FuetrekAudioEngine # ## -# `bZ[WNX +# 未定義メッセージを処理するクラス # -# @value vavi.sound.mfi.MfiMessage p -# (int,int,int,[B), (int,int,int,int) RXgN^‚ +# @value vavi.sound.mfi.MfiMessage を継承し +# (int,int,int,[B), (int,int,int,int) コンストラクタを持つもの # mfi.track.unknown=vavi.sound.mfi.vavi.track.UndefinedMessage @@ -81,51 +81,51 @@ mfi.track.unknown=vavi.sound.mfi.vavi.track.UndefinedMessage # ## -# m[gbZ[WNX +# ノートメッセージを処理するクラス # -# @value vavi.sound.mfi.NoteMessage p -# (int,int,int), (int,int,int,int) RXgN^‚ +# @value vavi.sound.mfi.NoteMessage を継承し +# (int,int,int), (int,int,int,int) コンストラクタを持つもの # mfi.track.note=vavi.sound.mfi.vavi.VaviNoteMessage # -# -------- Normal (gXe[^X) -------- +# -------- Normal (拡張ステータス情報) -------- # -# ---- gXe[^X A ---- +# ---- 拡張ステータス A ---- # -# vavi.sound.mfi.LongMessage p -# (int,int,int,[B) RXgN^‚ +# vavi.sound.mfi.LongMessage を継承し +# (int,int,int,[B) コンストラクタを持つもの # -# ׂė\ +# すべて予約 -# ---- gXe[^X B ---- +# ---- 拡張ステータス B ---- # -# vavi.sound.mfi.ShortMessage p -# (int,int,int,int) RXgN^‚ +# vavi.sound.mfi.ShortMessage を継承し +# (int,int,int,int) コンストラクタを持つもの # # -# 0xb# `lioɈˑȂ +# 0xb# チャンネルナンバに依存しない音源制御情報 # -# + 0xb0 }X^{[ +# + 0xb0 マスタボリューム mfi.track.255.b.176=vavi.sound.mfi.vavi.track.MasterVolumeMessage -# + 0xb1 }X^oX +# + 0xb1 マスタバランス #mfi.track.255.b.177=vavi.sound.mfi.vavi.track.MasterValanceMessage -# + 0xbc e|̑Εω +# + 0xbc テンポの相対変化 #mfi.track.255.b.188=vavi.sound.mfi.vavi.track.RelativeTempoMessage -# + 0xbd }X^{[̑Εω +# + 0xbd マスタボリュームの相対変化 #mfi.track.255.b.189=vavi.sound.mfi.vavi.track.RelativeMasterVolumeMessage -# + 0xbe XgbvEAhE~[g +# + 0xbe ストップ・アンド・ミュート #mfi.track.255.b.190=vavi.sound.mfi.vavi.track.StopAndMuteMessage -# + 0xbf Zbg +# + 0xbf 音源リセット #mfi.track.255.b.191=vavi.sound.mfi.vavi.track.ResetMessage -# + 0xba `lRtBO[V +# + 0xba チャンネルコンフィグレーション mfi.track.255.b.186=vavi.sound.mfi.vavi.track.ChannelConfigurationMessage # -# 0xc# e|bZ[W +# 0xc# テンポメッセージ # # + 0xc0 6 mfi.track.255.b.192=vavi.sound.mfi.vavi.track.TempoMessage @@ -141,7 +141,7 @@ mfi.track.255.b.196=vavi.sound.mfi.vavi.track.TempoMessage mfi.track.255.b.197=vavi.sound.mfi.vavi.track.TempoMessage # + 0xc6 384 mfi.track.255.b.198=vavi.sound.mfi.vavi.track.TempoMessage -# + 0xc7 \ +# + 0xc7 予約 mfi.track.255.b.199=vavi.sound.mfi.vavi.track.TempoMessage # + 0xc8 15 mfi.track.255.b.200=vavi.sound.mfi.vavi.track.TempoMessage @@ -157,17 +157,17 @@ mfi.track.255.b.204=vavi.sound.mfi.vavi.track.TempoMessage mfi.track.255.b.205=vavi.sound.mfi.vavi.track.TempoMessage # + 0xce 960 mfi.track.255.b.206=vavi.sound.mfi.vavi.track.TempoMessage -# + 0xcf \ +# + 0xcf 予約 mfi.track.255.b.207=vavi.sound.mfi.vavi.track.TempoMessage # -# 0xd# tǗ +# 0xd# 演奏管理情報 # -# + 0xd0 tʒu (L[|Cg) +# + 0xd0 演奏位置情報 (キューポイント) mfi.track.255.b.208=vavi.sound.mfi.vavi.track.CuePointMessage # + 0xdc NOP2 (No OPeration2) mfi.track.255.b.220=vavi.sound.mfi.vavi.track.Nop2Message -# + 0xdd [v|Cg +# + 0xdd ループポイント mfi.track.255.b.221=vavi.sound.mfi.vavi.track.LoopPointMessage # + 0xde NOP (No OPeration) mfi.track.255.b.222=vavi.sound.mfi.vavi.track.NopMessage @@ -175,39 +175,39 @@ mfi.track.255.b.222=vavi.sound.mfi.vavi.track.NopMessage mfi.track.255.b.223=vavi.sound.mfi.vavi.track.EndOfTrackMessage # -# 0xe# +# 0xe# 音源制御情報 # -# + 0xe0 FԍύX +# + 0xe0 音色番号変更 mfi.track.255.b.224=vavi.sound.mfi.vavi.track.ChangeVoiceMessage -# + 0xe1 FoNύX +# + 0xe1 音色バンク変更 mfi.track.255.b.225=vavi.sound.mfi.vavi.track.ChangeBankMessage -# + 0xe2 {[ύX +# + 0xe2 ボリューム変更 mfi.track.255.b.226=vavi.sound.mfi.vavi.track.VolumeMessage -# + 0xe3 p|bg +# + 0xe3 パンポット mfi.track.255.b.227=vavi.sound.mfi.vavi.track.PanpotMessage -# + 0xe4 sb`xhݒ +# + 0xe4 ピッチベンド設定 mfi.track.255.b.228=vavi.sound.mfi.vavi.track.PitchBendMessage -# + 0xe5 `l蓖 +# + 0xe5 チャンネル割り当て mfi.track.255.b.229=vavi.sound.mfi.vavi.track.ChannelChangeMessage -# + 0xe6 {[̑Εω +# + 0xe6 ボリュームの相対変化 mfi.track.255.b.230=vavi.sound.mfi.vavi.track.ExpressionMessage -# + 0xe7 sb`xhWݒ +# + 0xe7 ピッチベンドレンジ設定 mfi.track.255.b.231=vavi.sound.mfi.vavi.track.PitchBendRangeMessage -# + 0xe8 t@Csb`xh A ݒ +# + 0xe8 ファインピッチベンド A 設定 #mfi.track.255.b.232=vavi.sound.mfi.vavi.track.FinePitchBendAMessage -# + 0xe9 t@Csb`xh B ݒ +# + 0xe9 ファインピッチベンド B 設定 #mfi.track.255.b.233=vavi.sound.mfi.vavi.track.FinePitchBendBMessage -# + 0xea W[VfvXݒ +# + 0xea モジュレーションデプス設定 mfi.track.255.b.234=vavi.sound.mfi.vavi.track.ModulationDepthMessage -# ---- g ---- +# ---- 拡張情報 ---- # -# vavi.sound.mfi.SysexMessage p -# static SysexMessage readFrom(int,int,int,InputStream) \bhVOl`‚ +# vavi.sound.mfi.SysexMessage を継承し +# static SysexMessage readFrom(int,int,int,InputStream) メソッドシグネチャを持つもの # # -# 0xf# g +# 0xf# 拡張情報 # # + 0xf0 mfi.track.255.e.240=vavi.sound.mfi.vavi.track.VoiceEditMessage @@ -217,11 +217,11 @@ mfi.track.255.e.241=vavi.sound.mfi.vavi.track.ExtendedEditMessage #mfi.track.255.e.242=vavi.sound.mfi.vavi.track.CaraokeTextMessage # + 0xf3 #mfi.track.255.e.243=vavi.sound.mfi.vavi.track.CaraokeImageMessage -# + 0xfe mEWX^[hEbZ[Ww +# + 0xfe ノン・レジスタード・メッセージ指定 # length = dis.readShort() # id = dis.read(); # data ... -# 0: gp񎯕 ID +# 0: 拡張用情報識別 ID # 7654 3210 # ~~~~ ~~~~ # | +- 0001: DoCoMo @@ -229,138 +229,138 @@ mfi.track.255.e.241=vavi.sound.mfi.vavi.track.ExtendedEditMessage # +- 0000: reserved # : # 1110: reserved -# 1111: COgf[^ -# 0xff Ȃ玟(1:)Ɋgp񎯕 ID2 wł -# 1: data or gp񎯕 ID2 +# 1111: 海外向け拡張データ +# 0xff なら次(1:)に拡張用情報識別 ID2 を指定できる +# 1: data or 拡張用情報識別 ID2 # 2: : #mfi.track.255.e.254=NonRegisteredMessage -# + 0xff gp +# + 0xff 拡張用情報 mfi.track.255.e.255=vavi.sound.mfi.vavi.track.MachineDependentMessage # -# -------- Class A (mEWX^[hEbZ[W) (0x3f) -------- +# -------- Class A (ノン・レジスタード・メッセージ) (0x3f) -------- # -# ---- gXe[^X A ---- +# ---- 拡張ステータス A ---- # -# vavi.sound.mfi.LongMessage p -# (int,int,int,[B) RXgN^‚ +# vavi.sound.mfi.LongMessage を継承し +# (int,int,int,[B) コンストラクタを持つもの # -# ׂė\ +# すべて予約 -# ---- gXe[^X B ---- +# ---- 拡張ステータス B ---- # -# vavi.sound.mfi.ShortMessage p -# (int,int,int,int) RXgN^‚ +# vavi.sound.mfi.ShortMessage を継承し +# (int,int,int,int) コンストラクタを持つもの # -# ׂė\ +# すべて予約 -# ---- g ---- +# ---- 拡張情報 ---- # -# vavi.sound.mfi.SysexMessage p -# static SysexMessage readFrom(int,int,int,InputStream) \bhVOl`‚ +# vavi.sound.mfi.SysexMessage を継承し +# static SysexMessage readFrom(int,int,int,InputStream) メソッドシグネチャを持つもの # -# ׂė\ +# すべて予約 # # -------- Class B (0x7f) -------- # -# ---- gXe[^X A ---- +# ---- 拡張ステータス A ---- -# + 0x00 I[fBIvC +# + 0x00 オーディオプレイ mfi.track.127.a.0=vavi.sound.mfi.vavi.track.AudioPlayMessage -# + 0x01 I[fBIXgbv +# + 0x01 オーディオストップ mfi.track.127.a.1=vavi.sound.mfi.vavi.track.AudioStopMessage -# ---- gXe[^X B ---- +# ---- 拡張ステータス B ---- -# + 0x80 I[fBI`l{[ +# + 0x80 オーディオチャネルボリューム mfi.track.127.b.128=vavi.sound.mfi.vavi.track.AudioChannelVolumeMessage -# + 0x81 I[fBI`lp|bg +# + 0x81 オーディオチャネルパンポット mfi.track.127.b.129=vavi.sound.mfi.vavi.track.AudioChannelPanpotMessage # # 0x9# -# + 0x90 3D ʋ@\p +# + 0x90 3D 定位機能利用情報 #mfi.track.127.b.144= -# ---- g ---- +# ---- 拡張情報 ---- -# + 0xf0 3D ʏ +# + 0xf0 3D 定位情報 #mfi.track.127.e.240= # # -------- Class C (0xbf) -------- # -# ---- gXe[^X A ---- +# ---- 拡張ステータス A ---- # -# vavi.sound.mfi.LongMessage p -# (int,int,int,[B) RXgN^‚ +# vavi.sound.mfi.LongMessage を継承し +# (int,int,int,[B) コンストラクタを持つもの # -# ׂė\ +# すべて予約 -# ---- gXe[^X B ---- +# ---- 拡張ステータス B ---- # -# vavi.sound.mfi.ShortMessage p -# (int,int,int,int) RXgN^‚ +# vavi.sound.mfi.ShortMessage を継承し +# (int,int,int,int) コンストラクタを持つもの # -# ׂė\ +# すべて予約 -# ---- g ---- +# ---- 拡張情報 ---- # -# vavi.sound.mfi.SysexMessage p -# static SysexMessage readFrom(int,int,int,InputStream) \bhVOl`‚ +# vavi.sound.mfi.SysexMessage を継承し +# static SysexMessage readFrom(int,int,int,InputStream) メソッドシグネチャを持つもの # -# ׂė\ +# すべて予約 #------------------------------------------------------------------------------ # # AudioDataChunk SubChunk # -# vavi.sound.mfi.vavi.SubMessage p -# (String,[B) RXgN^‚ +# vavi.sound.mfi.vavi.SubMessage を継承し +# (String,[B) コンストラクタを持つもの # -# + ADPCM +# + ADPCM 情報 mfi.audio.adpm=vavi.sound.mfi.vavi.audio.AdpmMessage # # HeaderChunk SubChunk # -# vavi.sound.mfi.vavi.SubMessage p -# (String,[B) RXgN^‚ +# vavi.sound.mfi.vavi.SubMessage を継承し +# (String,[B) コンストラクタを持つもの # -# + ĔzzsŽʎq +# + 再配布不可識別子 mfi.header.sorc=vavi.sound.mfi.vavi.header.SorcMessage -# + ^Cg +# + タイトル情報 mfi.header.titl=vavi.sound.mfi.vavi.header.TitlMessage -# + o[W +# + バージョン情報 mfi.header.vers=vavi.sound.mfi.vavi.header.VersMessage -# + t +# + 日付情報 mfi.header.date=vavi.sound.mfi.vavi.header.DateMessage -# + Copyright +# + Copyright 情報 mfi.header.copy=vavi.sound.mfi.vavi.header.CopyMessage -# + f[^Ǘyѕی +# + データ管理及び保護情報 mfi.header.prot=vavi.sound.mfi.vavi.header.ProtMessage -# + m[gbZ[W +# + ノートメッセージ長情報 mfi.header.note=vavi.sound.mfi.vavi.header.NoteMessage -# + gXe[^X A bZ[W +# + 拡張ステータス A メッセージ長情報 mfi.header.exst=vavi.sound.mfi.vavi.header.ExstMessage -# + 쌠Ǘ +# + 著作権管理情報 mfi.header.auth=vavi.sound.mfi.vavi.header.AuthMessage -# + T|[g +# + サポート情報 mfi.header.supt=vavi.sound.mfi.vavi.header.SuptMessage -# + I[fBI`N +# + オーディオチャンク情報 mfi.header.ainf=vavi.sound.mfi.vavi.header.AinfMessage -# + 3D ʋ@\p +# + 3D 定位機能利用情報 #mfi.header.thrd=vavi.sound.mfi.vavi.header.ThrdMessage # @@ -376,96 +376,96 @@ encoding.read=JISAutoDetect # # -# ^Cxg +# メタイベント # -# + 0x01 eLXg +# + 0x01 テキスト midi.meta.1=vavi.sound.mfi.vavi.header.ProtMessage -# + 0x02 쌠\ +# + 0x02 著作権表示 midi.meta.2=vavi.sound.mfi.vavi.header.CopyMessage -# + 0x03 V[PX^gbN +# + 0x03 シーケンス名/トラック名 midi.meta.3=vavi.sound.mfi.vavi.header.TitlMessage # + 0x2f midi.meta.47=vavi.sound.mfi.vavi.track.EndOfTrackMessage -# + 0x51 Zbge| +# + 0x51 セットテンポ midi.meta.81=vavi.sound.mfi.vavi.track.TempoMessage -# + 0x58 q +# + 0x58 拍子 #midi.meta.88= -# + 0x59 +# + 0x59 調号 #midi.meta.89= -# + 0x7f V[PTŗL +# + 0x7f シーケンサ固有 #midi.meta.127= # -# `lbZ[W +# チャンネルメッセージ # -# + 0x8_ m[gIt +# + 0x8_ ノートオフ midi.short.128=vavi.sound.mfi.vavi.VaviNoteMessage -# + 0x9_ m[gI +# + 0x9_ ノートオン midi.short.144=vavi.sound.mfi.vavi.VaviNoteMessage -# + 0xa_ |tHjbNL[vbV[ +# + 0xa_ ポリフォニックキープレッシャー -# + 0xb_ Rg[`FW +# + 0xb_ コントロールチェンジ # -# + 0xb_ 0x00 oNZNg MSB +# + 0xb_ 0x00 バンクセレクト MSB midi.short.176.0=vavi.sound.mfi.vavi.track.MfiConvertibleMessage -# + 0xb_ 0x01 W[VfvX MSB +# + 0xb_ 0x01 モジュレーションデプス MSB midi.short.176.1=vavi.sound.mfi.vavi.track.ModulationDepthMessage -# + 0xb_ 0x02 uXRg[[ MSB -# + 0xb_ 0x04 tbgRg[[ MSB -# + 0xb_ 0x05 |^g^C MSB +# + 0xb_ 0x02 ブレスコントローラー MSB +# + 0xb_ 0x04 フットコントローラー MSB +# + 0xb_ 0x05 ポルタメントタイム MSB #midi.short.176.5= -# + 0xb_ 0x06 f[^Gg[ MSB +# + 0xb_ 0x06 データエントリー MSB midi.short.176.6=vavi.sound.mfi.vavi.track.MfiConvertibleMessage -# + 0xb_ 0x07 C{[ MSB +# + 0xb_ 0x07 メインボリューム MSB midi.short.176.7=vavi.sound.mfi.vavi.track.VolumeMessage -# + 0xb_ 0x08 oXRg[ MSB -# + 0xb_ 0x0a p|bg MSB +# + 0xb_ 0x08 バランスコントロール MSB +# + 0xb_ 0x0a パンポット MSB midi.short.176.10=vavi.sound.mfi.vavi.track.PanpotMessage -# + 0xb_ 0x0b GNXvbV MSB +# + 0xb_ 0x0b エクスプレッション MSB midi.short.176.11=vavi.sound.mfi.vavi.track.ExpressionMessage -# + 0xb_ 0x20 oNZNg LSB +# + 0xb_ 0x20 バンクセレクト LSB midi.short.176.32=vavi.sound.mfi.vavi.track.MfiConvertibleMessage -# + 0xb_ 0x30 ėpėpq-1 -# + 0xb_ 0x31 ėpėpq-2 -# + 0xb_ 0x32 ėpėpq-3 -# + 0xb_ 0x33 ėpėpq-4 -# + 0xb_ 0x40 z[h1 (_p[) -# + 0xb_ 0x41 |^g +# + 0xb_ 0x30 汎用汎用操作子-1 +# + 0xb_ 0x31 汎用汎用操作子-2 +# + 0xb_ 0x32 汎用汎用操作子-3 +# + 0xb_ 0x33 汎用汎用操作子-4 +# + 0xb_ 0x40 ホールド1 (ダンパー) +# + 0xb_ 0x41 ポルタメント #midi.short.176.65= -# + 0xb_ 0x42 \Xek[g -# + 0xb_ 0x43 \tgy_ -# + 0xb_ 0x44 K[gtbgXCb` -# + 0xb_ 0x45 z[h2 (t[Y) -# + 0xb_ 0x46 TEhRg[[1 (TEhoG[V) -# + 0xb_ 0x47 ]iX -# + 0xb_ 0x48 [X^C -# + 0xb_ 0x49 A^bN^C -# + 0xb_ 0x4a JbgIt -# + 0xb_ 0x4b fBPC^C -# + 0xb_ 0x4c ru[gCg -# + 0xb_ 0x4d ru[gfvX -# + 0xb_ 0x4e ru[gfBC -# + 0xb_ 0x50 ėpėpq-5 -# + 0xb_ 0x51 ėpėpq-6 -# + 0xb_ 0x52 ėpėpq-7 -# + 0xb_ 0x53 ėpėpq-8 -# + 0xb_ 0x54 |^g^C LSB -# + 0xb_ 0x5b ėpGtFNg1(o[u) +# + 0xb_ 0x42 ソステヌート +# + 0xb_ 0x43 ソフトペダル +# + 0xb_ 0x44 レガートフットスイッチ +# + 0xb_ 0x45 ホールド2 (フリーズ) +# + 0xb_ 0x46 サウンドコントローラー1 (サウンドバリエーション) +# + 0xb_ 0x47 レゾナンス +# + 0xb_ 0x48 リリースタイム +# + 0xb_ 0x49 アタックタイム +# + 0xb_ 0x4a カットオフ +# + 0xb_ 0x4b ディケイタイム +# + 0xb_ 0x4c ビブラートレイト +# + 0xb_ 0x4d ビブラートデプス +# + 0xb_ 0x4e ビブラートディレイ +# + 0xb_ 0x50 汎用汎用操作子-5 +# + 0xb_ 0x51 汎用汎用操作子-6 +# + 0xb_ 0x52 汎用汎用操作子-7 +# + 0xb_ 0x53 汎用汎用操作子-8 +# + 0xb_ 0x54 ポルタメントタイム LSB +# + 0xb_ 0x5b 汎用エフェクト1(リバーブ) #midi.short.176.91= -# + 0xb_ 0x5c ėpGtFNg2(g) +# + 0xb_ 0x5c 汎用エフェクト2(トレモロ) #midi.short.176.92= -# + 0xb_ 0x5d ėpGtFNg3(R[X) +# + 0xb_ 0x5d 汎用エフェクト3(コーラス) #midi.short.176.93= -# + 0xb_ 0x5e ėpGtFNg4(ZXe) +# + 0xb_ 0x5e 汎用エフェクト4(セレステ) #midi.short.176.94= -# + 0xb_ 0x5f ėpGtFNg5(tFCU) +# + 0xb_ 0x5f 汎用エフェクト5(フェイザ) #midi.short.176.95= -# + 0xb_ 0x60 f[^CNg -# + 0xb_ 0x61 f[^fNg +# + 0xb_ 0x60 データインクリメント +# + 0xb_ 0x61 データデクリメント # + 0xb_ 0x62 NRPN LSB midi.short.176.98=vavi.sound.mfi.vavi.track.MfiConvertibleMessage # + 0xb_ 0x63 NRPN MSB @@ -475,46 +475,46 @@ midi.short.176.100=vavi.sound.mfi.vavi.track.MfiConvertibleMessage # + 0xb_ 0x65 RPN MSB midi.short.176.101=vavi.sound.mfi.vavi.track.MfiConvertibleMessage -# + 0xb_ `l[hbZ[W +# + 0xb_ チャンネルモードメッセージ # -# + 0xb_ 0x78 (120) I[TEhIt -# + 0xb_ 0x79 (121) ZbgI[Rg[[ +# + 0xb_ 0x78 (120) オールサウンドオフ +# + 0xb_ 0x79 (121) リセットオールコントローラー #midi.short.176.121= -# + 0xb_ 0x7a (122) [JRg[ -# + 0xb_ 0x7b (123) I[m[gIt -# + 0xb_ 0x7c (124) IjIt -# + 0xb_ 0x7d (125) IjI -# + 0xb_ 0x7e (126) mI +# + 0xb_ 0x7a (122) ローカルコントロール +# + 0xb_ 0x7b (123) オールノートオフ +# + 0xb_ 0x7c (124) オムニオフ +# + 0xb_ 0x7d (125) オムニオン +# + 0xb_ 0x7e (126) モノオン #midi.short.176.126= -# + 0xb_ 0x7f (127) |I +# + 0xb_ 0x7f (127) ポリオン #midi.short.176.127= -# + 0xc_ vO`FW +# + 0xc_ プログラムチェンジ midi.short.192=vavi.sound.mfi.vavi.track.ChangeVoiceMessage -# + 0xd_ `lvbV[ +# + 0xd_ チャンネルプレッシャー -# + 0xe_ sb`xh`FW +# + 0xe_ ピッチベンドチェンジ midi.short.224=vavi.sound.mfi.vavi.track.PitchBendMessage -# + 0xf0 VXeGNXN[VubZ[W +# + 0xf0 システムエクスクルーシブメッセージ -# + 0xf_ VXeRbZ[W +# + 0xf_ システムコモンメッセージ # -# + 0xf1 MTC NH[^[t[ -# + 0xf2 \O|WV|C^ -# + 0xf3 \OZNg -# + 0xf6 `[NGXg -# + 0xf7 GhIuGNXN[Vu (EOX) +# + 0xf1 MTC クォーターフレーム +# + 0xf2 ソングポジションポインタ +# + 0xf3 ソングセレクト +# + 0xf6 チューンリクエスト +# + 0xf7 エンドオブエクスクルーシブ (EOX) -# + 0xf_ VXeA^CbZ[W +# + 0xf_ システムリアルタイムメッセージ # -# + 0xf8 ^C~ONbN -# + 0xfa X^[g -# + 0xfb ReBj[ -# + 0xfc Xgbv -# + 0xfe ANeBuZVO -# + 0xff VXeZbg +# + 0xf8 タイミングクロック +# + 0xfa スタート +# + 0xfb コンティニュー +# + 0xfc ストップ +# + 0xfe アクティブセンシング +# + 0xff システムリセット #------------------------------------------------------------------------------ diff --git a/src/main/resources/vavi/sound/sampled/FilterChain.properties b/src/main/resources/vavi/sound/sampled/FilterChain.properties index cdb0d30..1a01829 100644 --- a/src/main/resources/vavi/sound/sampled/FilterChain.properties +++ b/src/main/resources/vavi/sound/sampled/FilterChain.properties @@ -10,7 +10,7 @@ # ## -# @ˑ쐬NX +# 機種依存部作成クラス # #inputFilter.0=vavi.sound.sampled.SimpleResamplingInputFilter #inputFilter.1=vavi.sound.sampled.MonauralInputFilter diff --git a/src/main/resources/vavi/sound/sampled/mfi/MfiWithVoiceMaker.properties b/src/main/resources/vavi/sound/sampled/mfi/MfiWithVoiceMaker.properties index d04f1a4..84d7a01 100644 --- a/src/main/resources/vavi/sound/sampled/mfi/MfiWithVoiceMaker.properties +++ b/src/main/resources/vavi/sound/sampled/mfi/MfiWithVoiceMaker.properties @@ -10,7 +10,7 @@ # ## -# @ˑ쐬NX +# 機種依存部作成クラス # #class.d505=vavi.sound.sampled.mfi.type.d505 #class.n505=vavi.sound.sampled.mfi.type.n505 @@ -20,7 +20,7 @@ class.sh252=vavi.sound.sampled.mfi.type.sh252 class.sh900=vavi.sound.sampled.mfi.type.sh900 ## -# 쐬ҏ +# 作成者情報 # prot=vavi diff --git a/src/main/resources/vavi/sound/sampled/smaf/SmafWithVoiceMaker.properties b/src/main/resources/vavi/sound/sampled/smaf/SmafWithVoiceMaker.properties index 38a467e..059f077 100644 --- a/src/main/resources/vavi/sound/sampled/smaf/SmafWithVoiceMaker.properties +++ b/src/main/resources/vavi/sound/sampled/smaf/SmafWithVoiceMaker.properties @@ -10,7 +10,7 @@ # ## -# Rec̏ (',', '\' '\' ŃGXP[v邱) +# コンテンツの情報 (',', '\' は '\' でエスケープすること) # contentsInfo.subDatum.vn=vavi contentsInfo.subDatum.cr=(c) 2008 Vavisoft Inc. diff --git a/src/main/resources/vavi/sound/smaf/smaf.properties b/src/main/resources/vavi/sound/smaf/smaf.properties index be6defa..582a8f3 100644 --- a/src/main/resources/vavi/sound/smaf/smaf.properties +++ b/src/main/resources/vavi/sound/smaf/smaf.properties @@ -12,10 +12,10 @@ #------------------------------------------------------------------------------ ## -# Chunk ID ɑΉNXłB +# Chunk の ID に対応するクラスです。 # -# @name "chunk." + ChunkIDA'*' ̓ChJ[hɂȂ܂ -# @value NXAChunk pVOl` (byte[],int) ̃RXgN^‚ +# @name "chunk." + ChunkID、'*' はワイルドカードになります +# @value クラス名、Chunk を継承しシグネチャが (byte[],int) のコンストラクタを持つもの # @see vavi.sound.smaf.Chunk # chunk.MMMD=vavi.sound.smaf.chunk.FileChunk @@ -60,9 +60,9 @@ maker.43=vavi.sound.smaf.message.yamaha.YamahaMessage #------------------------------------------------------------------------------ ## -# tH[}bg^CvɑΉ AudioEngine +# フォーマットタイプに対応する AudioEngine # -# @name "audioEngine.format" + tH[}bg^Cv +# @name "audioEngine.format" + フォーマットタイプ # @see vavi.sound.smaf.chunk.WaveType # # WAVE Format 0 PCM Signed @@ -93,39 +93,39 @@ smaf.device.2=vavi.sound.smaf.MetaEventAdapter # @see "http://tech.millto.net/~pngnews/kndh/Page/jmmf.htm" # -# Acoustic Grand Piano +# Acoustic Grand Piano gm.1=F1 21 7B 8C A0 31 57 8C 00 00 11 22 44 -# Glockenspiel -gm.10=E3 D4 3F 5E 6F 84 DB E8 00 00 31 32 64 -# Drawbar Organ -gm.17=F1 3B 27 C4 F3 2B 13 C4 00 00 11 22 44 -# Electric Guitar(clean) -gm.28=71 71 1F 89 56 2A 5B BC 00 30 31 62 00 -# Overdriven Guitar -gm.30=71 7B 23 84 8C 2B 1F 0F 00 30 31 62 00 -# Distortion Guitar -gm.31=71 6B 23 84 0D 3B 1F 84 00 30 31 62 00 -# Acoustic Bass -gm.33=70 1A 5F 88 F1 2A 5B 94 00 01 12 24 00 -# Electric Bass(finger) -gm.34=F0 0A D3 C9 65 1A 97 F8 00 00 11 22 44 -# Electric Bass(pick) -gm.35=F0 0A D7 BD 45 1B 5B F0 00 00 11 22 44 -# String Emsemble1 -gm.49=72 49 BF C5 2F 9A 66 88 00 01 12 24 00 -# Voice Oohs -gm.54=71 9B 16 4D F0 2B 13 50 08 20 41 42 00 -# Synth Vox -gm.55=71 2A 1E 81 E6 5A 0E C0 08 01 12 24 00 -# Alto Sax -gm.66=F1 2B 1B 80 EC 3B 17 00 00 00 11 22 44 -# Lead1 -gm.81=72 9B 3F C1 98 4B 3F C0 00 10 21 42 00 -# Lead3 -gm.83=F1 3A 1F 55 B7 2A DE C0 00 00 11 22 44 -# Lead4 -gm.84=F1 39 66 D4 50 2B 67 8C 00 00 11 22 44 -# Lead5 -gm.85=71 5B 26 8D 0D 2B 26 84 08 10 21 42 00 +# Glockenspiel +gm.10=E3 D4 3F 5E 6F 84 DB E8 00 00 31 32 64 +# Drawbar Organ +gm.17=F1 3B 27 C4 F3 2B 13 C4 00 00 11 22 44 +# Electric Guitar(clean) +gm.28=71 71 1F 89 56 2A 5B BC 00 30 31 62 00 +# Overdriven Guitar +gm.30=71 7B 23 84 8C 2B 1F 0F 00 30 31 62 00 +# Distortion Guitar +gm.31=71 6B 23 84 0D 3B 1F 84 00 30 31 62 00 +# Acoustic Bass +gm.33=70 1A 5F 88 F1 2A 5B 94 00 01 12 24 00 +# Electric Bass(finger) +gm.34=F0 0A D3 C9 65 1A 97 F8 00 00 11 22 44 +# Electric Bass(pick) +gm.35=F0 0A D7 BD 45 1B 5B F0 00 00 11 22 44 +# String Emsemble1 +gm.49=72 49 BF C5 2F 9A 66 88 00 01 12 24 00 +# Voice Oohs +gm.54=71 9B 16 4D F0 2B 13 50 08 20 41 42 00 +# Synth Vox +gm.55=71 2A 1E 81 E6 5A 0E C0 08 01 12 24 00 +# Alto Sax +gm.66=F1 2B 1B 80 EC 3B 17 00 00 00 11 22 44 +# Lead1 +gm.81=72 9B 3F C1 98 4B 3F C0 00 10 21 42 00 +# Lead3 +gm.83=F1 3A 1F 55 B7 2A DE C0 00 00 11 22 44 +# Lead4 +gm.84=F1 39 66 D4 50 2B 67 8C 00 00 11 22 44 +# Lead5 +gm.85=71 5B 26 8D 0D 2B 26 84 08 10 21 42 00 ## diff --git a/src/test/java/t150_1.java b/src/test/java/t150_1.java index b35fa90..3a57cfb 100644 --- a/src/test/java/t150_1.java +++ b/src/test/java/t150_1.java @@ -11,11 +11,11 @@ import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.LineEvent; -import javax.sound.sampled.LineListener; import javax.sound.sampled.SourceDataLine; +import static vavi.sound.SoundUtil.volume; + /** * Play. @@ -49,17 +49,12 @@ void play(String filename) throws Exception { DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info); line.open(format); - line.addLineListener(new LineListener() { - public void update(LineEvent ev) { - if (LineEvent.Type.STOP == ev.getType()) { - System.exit(0); - } + line.addLineListener(ev -> { + if (LineEvent.Type.STOP == ev.getType()) { + System.exit(0); } }); -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); line.start(); byte[] buf = new byte[line.getBufferSize()]; int l; diff --git a/src/test/java/t150_3.java b/src/test/java/t150_3.java index 119f4ff..5fb245b 100644 --- a/src/test/java/t150_3.java +++ b/src/test/java/t150_3.java @@ -13,11 +13,11 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.LineEvent; -import javax.sound.sampled.LineListener; import javax.sound.sampled.SourceDataLine; +import static vavi.sound.SoundUtil.volume; + /** * Play PCM. @@ -72,17 +72,12 @@ void play(File file, int sampleRate, ByteOrder byteOrder) throws Exception { DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info); line.open(format); - line.addLineListener(new LineListener() { - public void update(LineEvent ev) { - if (LineEvent.Type.STOP == ev.getType()) { - System.exit(0); - } + line.addLineListener(ev -> { + if (LineEvent.Type.STOP == ev.getType()) { + System.exit(0); } }); -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); line.start(); byte[] buf = new byte[line.getBufferSize()]; int l = 0; diff --git a/src/test/java/t150_4.java b/src/test/java/t150_4.java index 7d257c6..3e3bd3f 100644 --- a/src/test/java/t150_4.java +++ b/src/test/java/t150_4.java @@ -13,11 +13,12 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.LineEvent; import javax.sound.sampled.LineListener; import javax.sound.sampled.SourceDataLine; +import static vavi.sound.SoundUtil.volume; + /** * Play PCM. @@ -75,10 +76,7 @@ public void update(LineEvent ev) { } } }); -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); line.start(); byte[] buf = new byte[line.getBufferSize()]; int l = 0; diff --git a/src/test/java/vavi/io/InputEngineOutputStreamTest.java b/src/test/java/vavi/io/InputEngineOutputStreamTest.java index ae9ce88..afe9701 100644 --- a/src/test/java/vavi/io/InputEngineOutputStreamTest.java +++ b/src/test/java/vavi/io/InputEngineOutputStreamTest.java @@ -40,7 +40,7 @@ class InputEngineOutputStreamTest { @BeforeAll static void setup() throws IOException { - Files.createDirectories(Paths.get("tmp")); + Files.createDirectories(Paths.get("tmp")); } @Test diff --git a/src/test/java/vavi/sound/adpcm/ccitt/G721InputStreamTest.java b/src/test/java/vavi/sound/adpcm/ccitt/G721InputStreamTest.java index 08cee95..8ac5361 100644 --- a/src/test/java/vavi/sound/adpcm/ccitt/G721InputStreamTest.java +++ b/src/test/java/vavi/sound/adpcm/ccitt/G721InputStreamTest.java @@ -17,7 +17,6 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.SourceDataLine; import org.junit.jupiter.api.BeforeEach; @@ -28,6 +27,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -76,10 +76,7 @@ public void test1() throws Exception { line.open(format); line.start(); -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); +volume(line, .2d); byte[] buf = new byte[1024]; while (is.available() > 0) { diff --git a/src/test/java/vavi/sound/adpcm/dvi/DviInputStreamTest.java b/src/test/java/vavi/sound/adpcm/dvi/DviInputStreamTest.java index 8a7ea1f..6b92a26 100644 --- a/src/test/java/vavi/sound/adpcm/dvi/DviInputStreamTest.java +++ b/src/test/java/vavi/sound/adpcm/dvi/DviInputStreamTest.java @@ -17,7 +17,6 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.SourceDataLine; import org.junit.jupiter.api.BeforeEach; @@ -28,6 +27,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -74,10 +74,7 @@ public void test1() throws Exception { SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info); line.open(format); line.start(); -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); byte[] buf = new byte[1024]; while (true) { diff --git a/src/test/java/vavi/sound/adpcm/ima/ImaInputStreamTest.java b/src/test/java/vavi/sound/adpcm/ima/ImaInputStreamTest.java index 3c7fc67..9ef32ab 100644 --- a/src/test/java/vavi/sound/adpcm/ima/ImaInputStreamTest.java +++ b/src/test/java/vavi/sound/adpcm/ima/ImaInputStreamTest.java @@ -19,7 +19,6 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.LineEvent; import javax.sound.sampled.LineListener; import javax.sound.sampled.SourceDataLine; @@ -34,6 +33,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -117,10 +117,7 @@ public void update(LineEvent ev) { } }); line.start(); -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); +volume(line, .2d); byte[] buf = new byte[bufferSize]; while (true) { diff --git a/src/test/java/vavi/sound/adpcm/ima/ImaOutputStreamTest.java b/src/test/java/vavi/sound/adpcm/ima/ImaOutputStreamTest.java index 197eb76..1d7e36c 100644 --- a/src/test/java/vavi/sound/adpcm/ima/ImaOutputStreamTest.java +++ b/src/test/java/vavi/sound/adpcm/ima/ImaOutputStreamTest.java @@ -19,7 +19,6 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.SourceDataLine; import org.junit.jupiter.api.BeforeEach; @@ -36,6 +35,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -99,10 +99,7 @@ public OutputStream getOutputStream(OutputStream out) throws IOException { line.open(audioFormat); line.start(); - FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); - double gain = .2d; // number between 0 and 1 (loudest) - float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); - gainControl.setValue(dB); + volume(line, .2d); byte[] buf = new byte[8192]; while (true) { @@ -173,10 +170,7 @@ public InputStream getInputStream(InputStream in) throws IOException { line.open(audioFormat); line.start(); - FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); - double gain = .2d; // number between 0 and 1 (loudest) - float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); - gainControl.setValue(dB); + volume(line, .2d); byte[] buf = new byte[8192]; while (true) { @@ -261,10 +255,7 @@ public void test3() throws Exception { line.open(audioFormat); line.start(); - FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); - double gain = .2d; // number between 0 and 1 (loudest) - float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); - gainControl.setValue(dB); + volume(line, .2d); byte[] buf = new byte[8192]; while (true) { diff --git a/src/test/java/vavi/sound/adpcm/ma/MaInputStreamTest.java b/src/test/java/vavi/sound/adpcm/ma/MaInputStreamTest.java index a972f1f..fcdf8dc 100644 --- a/src/test/java/vavi/sound/adpcm/ma/MaInputStreamTest.java +++ b/src/test/java/vavi/sound/adpcm/ma/MaInputStreamTest.java @@ -18,7 +18,6 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.LineEvent; import javax.sound.sampled.LineListener; import javax.sound.sampled.SourceDataLine; @@ -31,6 +30,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -87,10 +87,7 @@ public void update(LineEvent ev) { } }); line.start(); -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); byte[] buf = new byte[1024]; while (is.available() > 0) { diff --git a/src/test/java/vavi/sound/adpcm/ms/MsInputStreamTest.java b/src/test/java/vavi/sound/adpcm/ms/MsInputStreamTest.java index 6ab776d..5d2022c 100644 --- a/src/test/java/vavi/sound/adpcm/ms/MsInputStreamTest.java +++ b/src/test/java/vavi/sound/adpcm/ms/MsInputStreamTest.java @@ -19,7 +19,6 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.LineEvent; import javax.sound.sampled.LineListener; import javax.sound.sampled.SourceDataLine; @@ -34,6 +33,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -125,11 +125,7 @@ public void update(LineEvent ev) { } }); line.start(); - -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); +volume(line, .2d); byte[] buf = new byte[1024]; while (true) { diff --git a/src/test/java/vavi/sound/adpcm/ms/MsOutputStreamTest.java b/src/test/java/vavi/sound/adpcm/ms/MsOutputStreamTest.java index 7d865d3..e5a44bf 100644 --- a/src/test/java/vavi/sound/adpcm/ms/MsOutputStreamTest.java +++ b/src/test/java/vavi/sound/adpcm/ms/MsOutputStreamTest.java @@ -19,7 +19,6 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.LineEvent; import javax.sound.sampled.LineListener; import javax.sound.sampled.SourceDataLine; @@ -35,6 +34,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -177,10 +177,7 @@ public void update(LineEvent ev) { }); line.start(); - FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); - double gain = .2d; // number between 0 and 1 (loudest) - float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); - gainControl.setValue(dB); + volume(line, .2d); byte[] buf = new byte[1024]; while (true) { diff --git a/src/test/java/vavi/sound/adpcm/oki/OkiInputStreamTest.java b/src/test/java/vavi/sound/adpcm/oki/OkiInputStreamTest.java index 9a7e49c..f1cee88 100644 --- a/src/test/java/vavi/sound/adpcm/oki/OkiInputStreamTest.java +++ b/src/test/java/vavi/sound/adpcm/oki/OkiInputStreamTest.java @@ -17,7 +17,6 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.SourceDataLine; import org.junit.jupiter.api.BeforeEach; @@ -28,6 +27,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -74,10 +74,7 @@ public void test1() throws Exception { SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info); line.open(format); line.start(); -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); byte[] buf = new byte[1024]; while (true) { diff --git a/src/test/java/vavi/sound/adpcm/rohm/RohmInputStreamTest.java b/src/test/java/vavi/sound/adpcm/rohm/RohmInputStreamTest.java index 3eafe53..7c93d19 100644 --- a/src/test/java/vavi/sound/adpcm/rohm/RohmInputStreamTest.java +++ b/src/test/java/vavi/sound/adpcm/rohm/RohmInputStreamTest.java @@ -18,7 +18,6 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.LineEvent; import javax.sound.sampled.LineListener; import javax.sound.sampled.SourceDataLine; @@ -31,6 +30,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -87,10 +87,7 @@ public void update(LineEvent ev) { } }); line.start(); -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); byte[] buf = new byte[1024]; while (is.available() > 0) { diff --git a/src/test/java/vavi/sound/adpcm/vox/VoxInputStreamTest.java b/src/test/java/vavi/sound/adpcm/vox/VoxInputStreamTest.java index 9cadec3..17c53b3 100644 --- a/src/test/java/vavi/sound/adpcm/vox/VoxInputStreamTest.java +++ b/src/test/java/vavi/sound/adpcm/vox/VoxInputStreamTest.java @@ -18,7 +18,6 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.LineEvent; import javax.sound.sampled.LineListener; import javax.sound.sampled.SourceDataLine; @@ -31,6 +30,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -77,10 +77,7 @@ public void test1() throws Exception { SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info); line.open(format); line.start(); -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); byte[] buf = new byte[1024]; while (true) { diff --git a/src/test/java/vavi/sound/adpcm/yamaha/YamahaInputStreamTest.java b/src/test/java/vavi/sound/adpcm/yamaha/YamahaInputStreamTest.java index f722759..25c4f93 100644 --- a/src/test/java/vavi/sound/adpcm/yamaha/YamahaInputStreamTest.java +++ b/src/test/java/vavi/sound/adpcm/yamaha/YamahaInputStreamTest.java @@ -20,7 +20,6 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.LineEvent; import javax.sound.sampled.LineListener; import javax.sound.sampled.SourceDataLine; @@ -34,6 +33,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -80,10 +80,7 @@ public void test1() throws Exception { SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info); line.open(format); line.start(); -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); byte[] buf = new byte[1024]; while (true) { diff --git a/src/test/java/vavi/sound/adpcm/ym2608/Ym2608InputStreamTest.java b/src/test/java/vavi/sound/adpcm/ym2608/Ym2608InputStreamTest.java index 93c9134..c3cd038 100644 --- a/src/test/java/vavi/sound/adpcm/ym2608/Ym2608InputStreamTest.java +++ b/src/test/java/vavi/sound/adpcm/ym2608/Ym2608InputStreamTest.java @@ -17,7 +17,6 @@ import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.SourceDataLine; import org.junit.jupiter.api.BeforeEach; @@ -28,6 +27,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -44,15 +44,12 @@ public class Ym2608InputStreamTest { @BeforeEach public void setup() throws IOException { -// outFile = File.createTempFile("vavi", ".pcm"); -// outFile.deleteOnExit(); - outFile = new File("src/test/resources/vavi/sound/adpcm/ym2608/out_vavi.pcm"); + outFile = File.createTempFile("vavi", ".pcm"); + outFile.deleteOnExit(); +// outFile = new File("src/test/resources/vavi/sound/adpcm/ym2608/out_vavi.pcm"); Debug.println("outFile: " + outFile); } - /** - * TODO incomplete - */ @Test public void test1() throws Exception { @@ -79,10 +76,7 @@ public void test1() throws Exception { line.start(); byte[] buf = new byte[1024]; int l = 0; -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); while (is.available() > 0) { l = is.read(buf, 0, 1024); diff --git a/src/test/java/vavi/sound/adpcm/ym2608/Ym2608OutputStreamTest.java b/src/test/java/vavi/sound/adpcm/ym2608/Ym2608OutputStreamTest.java index be8a115..0d1c720 100644 --- a/src/test/java/vavi/sound/adpcm/ym2608/Ym2608OutputStreamTest.java +++ b/src/test/java/vavi/sound/adpcm/ym2608/Ym2608OutputStreamTest.java @@ -39,13 +39,12 @@ public class Ym2608OutputStreamTest { @BeforeEach public void setup() throws IOException { -// outFile = File.createTempFile("vavi", ".pcm"); -// outFile.deleteOnExit(); - outFile = new File("src/test/resources/vavi/sound/adpcm/ym2608/out_vavi.adpcm"); + outFile = File.createTempFile("vavi", ".pcm"); + outFile.deleteOnExit(); +// outFile = new File("src/test/resources/vavi/sound/adpcm/ym2608/out_vavi.adpcm"); Debug.println("outFile: " + outFile); } - /** */ @Test public void test1() throws Exception { OutputStream os = new FileOutputStream(outFile); diff --git a/src/test/java/vavi/sound/mfi/MfiSystemTest.java b/src/test/java/vavi/sound/mfi/MfiSystemTest.java index 181756a..adc45e0 100644 --- a/src/test/java/vavi/sound/mfi/MfiSystemTest.java +++ b/src/test/java/vavi/sound/mfi/MfiSystemTest.java @@ -6,15 +6,17 @@ package vavi.sound.mfi; +import java.io.BufferedInputStream; import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.CountDownLatch; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import vavi.util.Debug; -import static org.junit.jupiter.api.Assertions.fail; - /** * MfiSystemTest. @@ -22,12 +24,25 @@ * @author Naohide Sano (umjammer) * @version 0.00 2012/10/02 umjammer initial version
    */ -@Disabled public class MfiSystemTest { @Test - public void test() { - fail("Not yet implemented"); + public void test() throws Exception { + CountDownLatch cdl = new CountDownLatch(1); + Path inPath = Paths.get(MfiSystemTest.class.getResource("/test.mld").toURI()); + Sequencer sequencer = MfiSystem.getSequencer(); + sequencer.open(); + Sequence sequence = MfiSystem.getSequence(new BufferedInputStream(Files.newInputStream(inPath))); + sequencer.setSequence(sequence); + sequencer.addMetaEventListener(meta -> { +Debug.println(meta.getType()); + if (meta.getType() == 47) { + cdl.countDown(); + } + }); + sequencer.start(); + cdl.await(); + sequencer.close(); } //------------------------------------------------------------------------- @@ -38,19 +53,17 @@ public void test() { * usage: java -Djavax.sound.midi.Sequencer="#Real Time Sequencer" MfiSystem mfi_file ... */ public static void main(String[] args) throws Exception { - final Sequencer sequencer = MfiSystem.getSequencer(); + Sequencer sequencer = MfiSystem.getSequencer(); sequencer.open(); for (int i = 0; i < args.length; i++) { Debug.println("START: " + args[i]); Sequence sequence = MfiSystem.getSequence(new File(args[i])); sequencer.setSequence(sequence); if (i == args.length - 1) { - sequencer.addMetaEventListener(new MetaEventListener() { - public void meta(MetaMessage meta) { + sequencer.addMetaEventListener(meta -> { Debug.println(meta.getType()); - if (meta.getType() == 47) { - sequencer.close(); - } + if (meta.getType() == 47) { + sequencer.close(); } }); } diff --git a/src/test/java/vavi/sound/mfi/vavi/MfiContextTest.java b/src/test/java/vavi/sound/mfi/vavi/MfiContextTest.java index e479003..ba15bcd 100644 --- a/src/test/java/vavi/sound/mfi/vavi/MfiContextTest.java +++ b/src/test/java/vavi/sound/mfi/vavi/MfiContextTest.java @@ -6,19 +6,21 @@ package vavi.sound.mfi.vavi; +import java.io.BufferedInputStream; import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import javax.sound.midi.MidiFileFormat; import javax.sound.midi.MidiSystem; -import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import vavi.sound.mfi.MfiSystem; import vavi.util.Debug; -import static org.junit.jupiter.api.Assertions.fail; - /** * MfiContextTest. @@ -26,12 +28,29 @@ * @author Naohide Sano (umjammer) * @version 0.00 2012/10/02 umjammer initial version
    */ -@Disabled public class MfiContextTest { + static Path dir; + + @BeforeAll + static void setup() throws Exception { + dir = Paths.get("tmp"); + if (Files.exists(dir)) { + Files.createDirectories(dir); + } + } + @Test - public void test() { - fail("Not yet implemented"); + public void test() throws Exception { + Path inPath = Paths.get(MfiContextTest.class.getResource("/test.mid").toURI()); + javax.sound.midi.Sequence midiSequence = MidiSystem.getSequence(new BufferedInputStream(Files.newInputStream(inPath))); + MidiFileFormat midiFileFormat = MidiSystem.getMidiFileFormat(new BufferedInputStream(Files.newInputStream(inPath))); + int type = midiFileFormat.getType(); +Debug.println("type: " + type); + vavi.sound.mfi.Sequence mfiSequence = MfiSystem.toMfiSequence(midiSequence, type); + Path outPath = dir.resolve("MfiContextTest.mld"); + int r = MfiSystem.write(mfiSequence, VaviMfiFileFormat.FILE_TYPE, Files.newOutputStream(outPath)); +Debug.println("write: " + r); } //------------------------------------------------------------------------- diff --git a/src/test/java/vavi/sound/mfi/vavi/MfiConvertibleTest.java b/src/test/java/vavi/sound/mfi/vavi/MfiConvertibleTest.java new file mode 100644 index 0000000..fd24ce0 --- /dev/null +++ b/src/test/java/vavi/sound/mfi/vavi/MfiConvertibleTest.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 by Naohide Sano, All rights reserved. + * + * Programmed by Naohide Sano + */ + +package vavi.sound.mfi.vavi; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNull; + + +/** + * MfiConvertibleTest. + * + * @author Naohide Sano (umjammer) + * @version 0.00 2022/02/16 umjammer initial version
    + */ +class MfiConvertibleTest { + + @Test + void test() { + // exists in /vavi/sound/mfi/vavi/vavi.properties + MfiConvertible converter = MfiConvertible.factory.get("short.144"); + assertInstanceOf(VaviNoteMessage.class, converter); + // not exists + converter = MfiConvertible.factory.get("meta.144"); + assertNull(converter); + } +} + +/* */ diff --git a/src/test/java/vavi/sound/mfi/vavi/VaviMfiFileWriterTest.java b/src/test/java/vavi/sound/mfi/vavi/VaviMfiFileWriterTest.java index 6ebc59a..e3e42df 100644 --- a/src/test/java/vavi/sound/mfi/vavi/VaviMfiFileWriterTest.java +++ b/src/test/java/vavi/sound/mfi/vavi/VaviMfiFileWriterTest.java @@ -40,7 +40,7 @@ public class VaviMfiFileWriterTest { @BeforeAll static void setup() throws IOException { - Files.createDirectories(Paths.get("tmp")); + Files.createDirectories(Paths.get("tmp")); } /** diff --git a/src/test/java/vavi/sound/mfi/vavi/VaviMidiConverterTest.java b/src/test/java/vavi/sound/mfi/vavi/VaviMidiConverterTest.java index 8ce9bbe..77ce447 100644 --- a/src/test/java/vavi/sound/mfi/vavi/VaviMidiConverterTest.java +++ b/src/test/java/vavi/sound/mfi/vavi/VaviMidiConverterTest.java @@ -6,20 +6,23 @@ package vavi.sound.mfi.vavi; +import java.io.BufferedInputStream; import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.CountDownLatch; import javax.sound.midi.MidiSystem; import javax.sound.midi.Sequence; import javax.sound.midi.Sequencer; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import vavi.sound.mfi.MfiSystem; +import vavi.sound.mfi.MfiSystemTest; import vavi.util.Debug; -import static org.junit.jupiter.api.Assertions.fail; - /** * VaviMidiConverterTest. @@ -27,12 +30,30 @@ * @author Naohide Sano (umjammer) * @version 0.00 2012/10/02 umjammer initial version
    */ -@Disabled public class VaviMidiConverterTest { @Test - public void test() { - fail("Not yet implemented"); + public void test() throws Exception { + CountDownLatch cdl = new CountDownLatch(1); + Path inPath = Paths.get(MfiSystemTest.class.getResource("/test.mld").toURI()); + vavi.sound.mfi.Sequence mfiSequence = MfiSystem.getSequence(new BufferedInputStream(Files.newInputStream(inPath))); + Sequence midiSequence = MfiSystem.toMidiSequence(mfiSequence); + + Sequencer midiSequencer = MidiSystem.getSequencer(); +Debug.println("midiSequencer: " + midiSequencer); +Debug.println("midiSequencer:T: " + midiSequencer.getTransmitter()); +Debug.println("midiSequencer:R: " + midiSequencer.getReceiver()); + midiSequencer.open(); + midiSequencer.setSequence(midiSequence); + midiSequencer.addMetaEventListener(meta -> { +Debug.println(meta.getType()); + if (meta.getType() == 47) { + cdl.countDown(); + } + }); + midiSequencer.start(); + cdl.await(); + midiSequencer.close(); } //------------------------------------------------------------------------- diff --git a/src/test/java/vavi/sound/mfi/vavi/sequencer/AudioEngineTest.java b/src/test/java/vavi/sound/mfi/vavi/sequencer/AudioEngineTest.java index 399c2ec..64b79e7 100644 --- a/src/test/java/vavi/sound/mfi/vavi/sequencer/AudioEngineTest.java +++ b/src/test/java/vavi/sound/mfi/vavi/sequencer/AudioEngineTest.java @@ -8,9 +8,14 @@ import org.junit.jupiter.api.Test; +import vavi.sound.mobile.AudioEngine; import vavi.sound.mobile.AudioEngine.Util; +import vavi.sound.mobile.FuetrekAudioEngine; +import vavi.sound.mobile.RohmAudioEngine; import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNull; /** @@ -36,6 +41,19 @@ public void test2() { byte[] stereo = Util.toStereo(monoL, monoR, 4, null); assertArrayEquals(new byte[] { (byte) 0xa1, (byte) 0xb2, (byte) 0xc3, (byte) 0xd4 }, stereo); } + + + @Test + public void test3() { + // exists in /vavi/sound/mfi/vavi/vavi.properties + AudioEngine audioEngine = AudioDataSequencer.Factory.getAudioEngine(0x80); + assertInstanceOf(RohmAudioEngine.class, audioEngine); + audioEngine = AudioDataSequencer.Factory.getAudioEngine(0x81); + assertInstanceOf(FuetrekAudioEngine.class, audioEngine); + // not exists + audioEngine = AudioDataSequencer.Factory.getAudioEngine(0x82); + assertNull(audioEngine); + } } /* */ diff --git a/src/test/java/vavi/sound/mfi/vavi/sequencer/MachineDependentSequencerTest.java b/src/test/java/vavi/sound/mfi/vavi/sequencer/MachineDependentSequencerTest.java index 028b768..2ca400b 100644 --- a/src/test/java/vavi/sound/mfi/vavi/sequencer/MachineDependentSequencerTest.java +++ b/src/test/java/vavi/sound/mfi/vavi/sequencer/MachineDependentSequencerTest.java @@ -8,6 +8,7 @@ import org.junit.jupiter.api.Test; +import vavi.util.Debug; import vavi.util.properties.PrefixedClassPropertiesFactory; import vavi.util.properties.PrefixedPropertiesFactory; @@ -28,7 +29,7 @@ public void test() { new PrefixedClassPropertiesFactory<>("/vavi/sound/mfi/vavi/vavi.properties", "sequencer.vendor."); MachineDependentSequencer mds = machineDependentSequencerFactory.get(97); - System.err.println(mds); +Debug.println(mds); assertTrue(vavi.sound.mfi.vavi.mitsubishi.MitsubishiSequencer.class.isInstance(mds)); mds = machineDependentSequencerFactory.get(17); diff --git a/src/test/java/vavi/sound/midi/MidiUtilTest.java b/src/test/java/vavi/sound/midi/MidiUtilTest.java new file mode 100644 index 0000000..9952cd7 --- /dev/null +++ b/src/test/java/vavi/sound/midi/MidiUtilTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2008 by Naohide Sano, All rights reserved. + * + * Programmed by Naohide Sano + */ + +package vavi.sound.midi; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutput; +import java.io.DataOutputStream; +import java.io.File; + +import javax.sound.midi.MidiSystem; +import javax.sound.midi.Sequence; +import javax.sound.midi.Sequencer; + +import org.junit.jupiter.api.Test; + +import vavi.sound.smaf.SmafMessage; +import vavi.util.Debug; + +import static org.junit.jupiter.api.Assertions.assertEquals; + + +/** + * MidiUtilTest. + * + * @author Naohide Sano (nsano) + * @version 0.00 080701 nsano initial version
    + */ +public class MidiUtilTest { + + /** + * Tests {@link HackedChunk#readOneToFour(DataInputStream)}. + *
    +     *  実際の数値 | 可変長での表現
    +     * ------------+-------------
    +     *  00000000   | 00
    +     *  00000040   | 40
    +     *  0000007F   | 7F
    +     *  00000080   | 81 00
    +     *  00002000   | C0 00
    +     *  00003FFF   | FF 7F
    +     *  00004000   | 81 80 00
    +     *  00100000   | C0 80 00
    +     *  001FFFFF   | FF FF 7F
    +     *  00200000   | 81 80 80 00
    +     *  08000000   | C0 80 80 00
    +     *  0FFFFFFF   | FF FF FF 7F
    +     * 
    + */ + @Test + public void testReadOneToFour() throws Exception { + assertEquals(0x00000000, MidiUtil.readVariableLength(new DataInputStream(new ByteArrayInputStream(new byte[] { 0x00 })))); + assertEquals(0x00000040, MidiUtil.readVariableLength(new DataInputStream(new ByteArrayInputStream(new byte[] { 0x40 })))); + assertEquals(0x0000007F, MidiUtil.readVariableLength(new DataInputStream(new ByteArrayInputStream(new byte[] { 0x7F })))); + assertEquals(0x00000080, MidiUtil.readVariableLength(new DataInputStream(new ByteArrayInputStream(new byte[] { (byte) 0x81, 0x00 })))); + assertEquals(0x00002000, MidiUtil.readVariableLength(new DataInputStream(new ByteArrayInputStream(new byte[] { (byte) 0xC0, 0x00 })))); + assertEquals(0x00003FFF, MidiUtil.readVariableLength(new DataInputStream(new ByteArrayInputStream(new byte[] { (byte) 0xFF, 0x7F })))); + assertEquals(0x00004000, MidiUtil.readVariableLength(new DataInputStream(new ByteArrayInputStream(new byte[] { (byte) 0x81, (byte) 0x80, 0x00 })))); + assertEquals(0x00100000, MidiUtil.readVariableLength(new DataInputStream(new ByteArrayInputStream(new byte[] { (byte) 0xC0, (byte) 0x80, 0x00 })))); + assertEquals(0x001FFFFF, MidiUtil.readVariableLength(new DataInputStream(new ByteArrayInputStream(new byte[] { (byte) 0xFF, (byte) 0xFF, 0x7F })))); + assertEquals(0x00200000, MidiUtil.readVariableLength(new DataInputStream(new ByteArrayInputStream(new byte[] { (byte) 0x81, (byte) 0x80, (byte) 0x80, 0x00 })))); + assertEquals(0x08000000, MidiUtil.readVariableLength(new DataInputStream(new ByteArrayInputStream(new byte[] { (byte) 0xC0, (byte) 0x80, (byte) 0x80, 0x00 })))); + assertEquals(0x0FFFFFFF, MidiUtil.readVariableLength(new DataInputStream(new ByteArrayInputStream(new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, 0x7F })))); + } + + /** + * @param args 0: midi + */ + public static void main(String[] args) throws Exception { + File file = new File(args[0]); + + Sequence sequence = MidiSystem.getSequence(file); +Debug.println("sequence: " + sequence); + + Sequencer sequencer = MidiSystem.getSequencer(); +Debug.println("sequencer: " + sequencer); + sequencer.open(); + sequencer.setSequence(sequence); + sequencer.start(); + while (sequencer.isRunning()) { + try { Thread.sleep(100); } catch (Exception e) {} + } + sequencer.stop(); + sequencer.close(); + } + + /** + * Tests {@link SmafMessage#writeOneToTwo(DataOutput, int)}. + */ + @Test + public void test01() throws Exception { + assertEquals(15000 / 4, wr(15000 / 4)); + assertEquals(0x0040, wr(0x0040)); + assertEquals(0x007f, wr(0x007f)); + assertEquals(0x0080, wr(0x0080)); + assertEquals(0x2000, wr(0x2000)); + assertEquals(0x3fff, wr(0x3fff)); + } + + /** + * {@link SmafMessage#writeOneToTwo(DataOutput, int)} + */ + private int wr(int v) throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + MidiUtil.writeVarInt(new DataOutputStream(baos), v); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + return MidiUtil.readVariableLength(new DataInputStream(bais)); + } +} + +/* */ diff --git a/src/test/java/vavi/sound/midi/Test.java b/src/test/java/vavi/sound/midi/Test.java deleted file mode 100644 index a3ac750..0000000 --- a/src/test/java/vavi/sound/midi/Test.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2008 by Naohide Sano, All rights reserved. - * - * Programmed by Naohide Sano - */ - -package vavi.sound.midi; - -import java.io.File; - -import javax.sound.midi.MidiSystem; -import javax.sound.midi.Sequence; -import javax.sound.midi.Sequencer; - -import vavi.util.Debug; - - -/** - * Test. - * - * @author Naohide Sano (nsano) - * @version 0.00 080701 nsano initial version
    - */ -public class Test { - - /** - * @param args 0: midi - */ - public static void main(String[] args) throws Exception { - File file = new File(args[0]); - - Sequence sequence = MidiSystem.getSequence(file); -Debug.println("sequence: " + sequence); - - Sequencer sequencer = MidiSystem.getSequencer(); -Debug.println("sequencer: " + sequencer); - sequencer.open(); - sequencer.setSequence(sequence); - sequencer.start(); - while (sequencer.isRunning()) { - try { Thread.sleep(100); } catch (Exception e) {} - } - sequencer.stop(); - sequencer.close(); - } -} - -/* */ diff --git a/src/test/java/vavi/sound/midi/mfi/MfiMidiFileReaderTest.java b/src/test/java/vavi/sound/midi/mfi/MfiMidiFileReaderTest.java index 7b379d5..8581255 100644 --- a/src/test/java/vavi/sound/midi/mfi/MfiMidiFileReaderTest.java +++ b/src/test/java/vavi/sound/midi/mfi/MfiMidiFileReaderTest.java @@ -7,6 +7,8 @@ package vavi.sound.midi.mfi; import java.io.File; +import java.io.InputStream; +import java.util.concurrent.CountDownLatch; import javax.sound.midi.MetaEventListener; import javax.sound.midi.MetaMessage; @@ -14,13 +16,10 @@ import javax.sound.midi.Sequence; import javax.sound.midi.Sequencer; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import vavi.util.Debug; -import static org.junit.jupiter.api.Assertions.fail; - /** * MfiMidiFileReaderTest. @@ -28,12 +27,30 @@ * @author Naohide Sano (umjammer) * @version 0.00 2012/10/02 umjammer initial version
    */ -@Disabled public class MfiMidiFileReaderTest { @Test - public void test() { - fail("Not yet implemented"); + public void test() throws Exception { + InputStream is = MfiVaviSequenceTest.class.getResourceAsStream("/test.mld"); + + CountDownLatch cdl = new CountDownLatch(1); + + Sequencer sequencer = MidiSystem.getSequencer(); + sequencer.open(); + Sequence sequence = MidiSystem.getSequence(is); +Debug.println(sequence); + sequencer.setSequence(sequence); + sequencer.addMetaEventListener(new MetaEventListener() { + public void meta(MetaMessage meta) { +Debug.println(meta.getType()); + if (meta.getType() == 47) { + cdl.countDown(); + } + } + }); + sequencer.start(); + cdl.await(); + sequencer.close(); } //---- @@ -43,6 +60,8 @@ public void test() { * @param args [0] filename */ public static void main(String[] args) throws Exception { + CountDownLatch cdl = new CountDownLatch(1); + Sequencer sequencer = MidiSystem.getSequencer(); sequencer.open(); Sequence sequence = MidiSystem.getSequence(new File(args[0])); @@ -52,11 +71,13 @@ public static void main(String[] args) throws Exception { public void meta(MetaMessage meta) { Debug.println(meta.getType()); if (meta.getType() == 47) { - System.exit(0); + cdl.countDown(); } } }); sequencer.start(); + cdl.await(); + sequencer.close(); } } diff --git a/src/test/java/vavi/sound/midi/mfi/MfiVaviSequenceTest.java b/src/test/java/vavi/sound/midi/mfi/MfiVaviSequenceTest.java index 56f46eb..1899876 100644 --- a/src/test/java/vavi/sound/midi/mfi/MfiVaviSequenceTest.java +++ b/src/test/java/vavi/sound/midi/mfi/MfiVaviSequenceTest.java @@ -7,16 +7,17 @@ package vavi.sound.midi.mfi; import java.io.File; +import java.io.InputStream; import javax.sound.midi.MidiFileFormat; import javax.sound.midi.MidiSystem; +import javax.sound.midi.Sequence; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import vavi.util.StringUtil; -import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.Assertions.assertNotNull; /** @@ -25,12 +26,34 @@ * @author Naohide Sano (umjammer) * @version 0.00 2012/10/02 umjammer initial version
    */ -@Disabled public class MfiVaviSequenceTest { @Test - public void test() { - fail("Not yet implemented"); + public void test0() throws Exception { + InputStream is = MfiVaviSequenceTest.class.getResourceAsStream("/test.mld"); + Sequence sequence = new MfiMidiFileReader().getSequence(is); + assertNotNull(sequence); + } + + @Test + public void test2() throws Exception { + InputStream is = MfiVaviSequenceTest.class.getResourceAsStream("/test.mld"); + Sequence sequence = MidiSystem.getSequence(is); + assertNotNull(sequence); + } + + @Test + public void test3() throws Exception { + InputStream is = MfiVaviSequenceTest.class.getResourceAsStream("/test.mld"); + MidiFileFormat format= new MfiMidiFileReader().getMidiFileFormat(is); + assertNotNull(format); + } + + @Test + public void test4() throws Exception { + InputStream is = MfiVaviSequenceTest.class.getResourceAsStream("/test.mld"); + MidiFileFormat format= MidiSystem.getMidiFileFormat(is); + assertNotNull(format); } //---- diff --git a/src/test/java/vavi/sound/midi/smaf/SmafVaviSequenceTest.java b/src/test/java/vavi/sound/midi/smaf/SmafVaviSequenceTest.java index fbf16e7..db64075 100644 --- a/src/test/java/vavi/sound/midi/smaf/SmafVaviSequenceTest.java +++ b/src/test/java/vavi/sound/midi/smaf/SmafVaviSequenceTest.java @@ -7,16 +7,17 @@ package vavi.sound.midi.smaf; import java.io.File; +import java.io.InputStream; import javax.sound.midi.MidiFileFormat; import javax.sound.midi.MidiSystem; +import javax.sound.midi.Sequence; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import vavi.util.StringUtil; -import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.Assertions.assertNotNull; /** @@ -25,12 +26,34 @@ * @author Naohide Sano (umjammer) * @version 0.00 2012/10/02 umjammer initial version
    */ -@Disabled public class SmafVaviSequenceTest { @Test - public void test() { - fail("Not yet implemented"); + public void test1() throws Exception { + InputStream is = SmafVaviSequenceTest.class.getResourceAsStream("/test.mmf"); + Sequence sequence = new SmafMidiFileReader().getSequence(is); + assertNotNull(sequence); + } + + @Test + public void test2() throws Exception { + InputStream is = SmafVaviSequenceTest.class.getResourceAsStream("/test.mmf"); + Sequence sequence = MidiSystem.getSequence(is); + assertNotNull(sequence); + } + + @Test + public void test3() throws Exception { + InputStream is = SmafVaviSequenceTest.class.getResourceAsStream("/test.mmf"); + MidiFileFormat mff = new SmafMidiFileReader().getMidiFileFormat(is); + assertNotNull(mff); + } + + @Test + public void test4() throws Exception { + InputStream is = SmafVaviSequenceTest.class.getResourceAsStream("/test.mmf"); + MidiFileFormat mff = MidiSystem.getMidiFileFormat(is); + assertNotNull(mff); } //---- diff --git a/src/test/java/vavi/sound/mobile/BasicAudioEngineTest.java b/src/test/java/vavi/sound/mobile/BasicAudioEngineTest.java index 2f5dc76..23e9198 100644 --- a/src/test/java/vavi/sound/mobile/BasicAudioEngineTest.java +++ b/src/test/java/vavi/sound/mobile/BasicAudioEngineTest.java @@ -6,19 +6,24 @@ package vavi.sound.mobile; +import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.CountDownLatch; + +import javax.sound.sampled.SourceDataLine; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import vavi.sound.mfi.MfiSystemTest; import vavi.util.Debug; -import static org.junit.jupiter.api.Assertions.fail; - /** * BasicAudioEngineTest. @@ -26,12 +31,25 @@ * @author Naohide Sano (umjammer) * @version 0.00 2012/10/02 umjammer initial version
    */ -@Disabled public class BasicAudioEngineTest { @Test - public void test() { - fail("Not yet implemented"); + public void test() throws Exception { + CountDownLatch cdl = new CountDownLatch(1); + Path inPath = Paths.get(MfiSystemTest.class.getResource("/test.mld").toURI()); + vavi.sound.mfi.Sequencer sequencer = vavi.sound.mfi.MfiSystem.getSequencer(); + sequencer.open(); + vavi.sound.mfi.Sequence sequence = vavi.sound.mfi.MfiSystem.getSequence(new BufferedInputStream(Files.newInputStream(inPath))); + sequencer.setSequence(sequence); + sequencer.addMetaEventListener(meta -> { +Debug.println(meta.getType()); + if (meta.getType() == 47) { + cdl.countDown(); + } + }); + sequencer.start(); + cdl.await(); + sequencer.close(); } //------------------------------------------------------------------------- @@ -42,6 +60,40 @@ public void test() { /** */ private static String pcmFileName; + + /** */ + public static class WrappedLineOutputStream extends OutputStream { + SourceDataLine line; + OutputStream out; + public WrappedLineOutputStream(SourceDataLine line, OutputStream out) { + this.out = out; + this.line = line; + } + @Override + public void write(int b) throws IOException { + write(new byte[] { (byte) b }); + } + @Override + public void write(byte[] b, int off, int len) throws IOException { + line.write(b, off, len); + if (out != null) { + out.write(b, off, len); + } + } + @Override + public void flush() throws IOException { + if (out != null) { + out.flush(); + } + } + /** {@link #line} not closed */ + @Override + public void close() throws IOException { + if (out != null) { + out.close(); + } + } + } /** */ void debug1(byte[] adpcm) { try { @@ -97,19 +149,20 @@ public static void main(String[] args) throws Exception { pcmFileName = args[2]; } + CountDownLatch cdl = new CountDownLatch(1); vavi.sound.mfi.Sequencer sequencer = vavi.sound.mfi.MfiSystem.getSequencer(); sequencer.open(); vavi.sound.mfi.Sequence sequence = vavi.sound.mfi.MfiSystem.getSequence(new File(args[0])); sequencer.setSequence(sequence); - sequencer.addMetaEventListener(new vavi.sound.mfi.MetaEventListener() { - public void meta(vavi.sound.mfi.MetaMessage meta) { + sequencer.addMetaEventListener(meta -> { Debug.println(meta.getType()); - if (meta.getType() == 47) { - System.exit(0); - } + if (meta.getType() == 47) { + cdl.countDown(); } }); sequencer.start(); + cdl.await(); + sequencer.close(); } } diff --git a/src/test/java/vavi/sound/pcm/resampling/ssrc/SSRCTest.java b/src/test/java/vavi/sound/pcm/resampling/ssrc/SSRCTest.java index 8ff364c..268c3d6 100644 --- a/src/test/java/vavi/sound/pcm/resampling/ssrc/SSRCTest.java +++ b/src/test/java/vavi/sound/pcm/resampling/ssrc/SSRCTest.java @@ -16,7 +16,6 @@ import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.SourceDataLine; import org.junit.jupiter.api.BeforeAll; @@ -31,6 +30,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +import static vavi.sound.SoundUtil.volume; /** @@ -68,10 +68,7 @@ public void test1() throws Exception { DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info); line.open(format); -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); line.start(); byte[] buf = new byte[1024]; int l; @@ -102,10 +99,7 @@ public void test3() throws Exception { DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info); line.open(format); -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); line.start(); byte[] buf = new byte[1024]; int l; @@ -180,10 +174,7 @@ public void test4() throws Exception { SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info); line.open(outFormat); // volume -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); line.start(); byte[] buf = new byte[0x10000]; int f = format.getFrameSize() * format.getChannels(); diff --git a/src/test/java/vavi/sound/sampled/adpcm/ccitt/CcittAudioFileReaderTest.java b/src/test/java/vavi/sound/sampled/adpcm/ccitt/CcittAudioFileReaderTest.java index b35b950..3a0f7e0 100644 --- a/src/test/java/vavi/sound/sampled/adpcm/ccitt/CcittAudioFileReaderTest.java +++ b/src/test/java/vavi/sound/sampled/adpcm/ccitt/CcittAudioFileReaderTest.java @@ -17,7 +17,6 @@ import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.SourceDataLine; import org.junit.jupiter.api.BeforeEach; @@ -28,6 +27,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -89,10 +89,7 @@ public void test1() throws Exception { line.start(); byte[] buf = new byte[1024]; int l = 0; -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); while (oais.available() > 0) { l = oais.read(buf, 0, 1024); diff --git a/src/test/java/vavi/sound/sampled/adpcm/dvi/DviAudioFileReaderTest.java b/src/test/java/vavi/sound/sampled/adpcm/dvi/DviAudioFileReaderTest.java index ae06449..1685a72 100644 --- a/src/test/java/vavi/sound/sampled/adpcm/dvi/DviAudioFileReaderTest.java +++ b/src/test/java/vavi/sound/sampled/adpcm/dvi/DviAudioFileReaderTest.java @@ -17,7 +17,6 @@ import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.SourceDataLine; import org.junit.jupiter.api.BeforeEach; @@ -28,6 +27,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -89,10 +89,7 @@ public void test1() throws Exception { line.start(); byte[] buf = new byte[1024]; int l = 0; -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); while (oais.available() > 0) { l = oais.read(buf, 0, 1024); diff --git a/src/test/java/vavi/sound/sampled/adpcm/ima/ImaAudioFileReaderTest.java b/src/test/java/vavi/sound/sampled/adpcm/ima/ImaAudioFileReaderTest.java index aa543ef..edc4f44 100644 --- a/src/test/java/vavi/sound/sampled/adpcm/ima/ImaAudioFileReaderTest.java +++ b/src/test/java/vavi/sound/sampled/adpcm/ima/ImaAudioFileReaderTest.java @@ -17,7 +17,6 @@ import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.SourceDataLine; import org.junit.jupiter.api.BeforeEach; @@ -29,6 +28,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -91,10 +91,7 @@ public void test1() throws Exception { line.start(); byte[] buf = new byte[1024]; int l = 0; -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); while (oais.available() > 0) { l = oais.read(buf, 0, 1024); diff --git a/src/test/java/vavi/sound/sampled/adpcm/ma/MaAudioFileReaderTest.java b/src/test/java/vavi/sound/sampled/adpcm/ma/MaAudioFileReaderTest.java index c77ded6..4943d3a 100644 --- a/src/test/java/vavi/sound/sampled/adpcm/ma/MaAudioFileReaderTest.java +++ b/src/test/java/vavi/sound/sampled/adpcm/ma/MaAudioFileReaderTest.java @@ -17,7 +17,6 @@ import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.SourceDataLine; import org.junit.jupiter.api.BeforeEach; @@ -28,6 +27,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -89,10 +89,7 @@ public void test1() throws Exception { line.start(); byte[] buf = new byte[1024]; int l = 0; -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); while (oais.available() > 0) { l = oais.read(buf, 0, 1024); diff --git a/src/test/java/vavi/sound/sampled/adpcm/ms/MsAudioFileReaderTest.java b/src/test/java/vavi/sound/sampled/adpcm/ms/MsAudioFileReaderTest.java index 8ded29d..42f2b4b 100644 --- a/src/test/java/vavi/sound/sampled/adpcm/ms/MsAudioFileReaderTest.java +++ b/src/test/java/vavi/sound/sampled/adpcm/ms/MsAudioFileReaderTest.java @@ -17,7 +17,6 @@ import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.SourceDataLine; import org.junit.jupiter.api.BeforeEach; @@ -29,6 +28,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -91,10 +91,7 @@ public void test1() throws Exception { line.start(); byte[] buf = new byte[1024]; int l = 0; -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); while (oais.available() > 0) { l = oais.read(buf, 0, 1024); diff --git a/src/test/java/vavi/sound/sampled/adpcm/oki/OkiAudioFileReaderTest.java b/src/test/java/vavi/sound/sampled/adpcm/oki/OkiAudioFileReaderTest.java index d03e4ae..779a217 100644 --- a/src/test/java/vavi/sound/sampled/adpcm/oki/OkiAudioFileReaderTest.java +++ b/src/test/java/vavi/sound/sampled/adpcm/oki/OkiAudioFileReaderTest.java @@ -17,7 +17,6 @@ import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.SourceDataLine; import org.junit.jupiter.api.BeforeEach; @@ -28,6 +27,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -89,10 +89,7 @@ public void test1() throws Exception { line.start(); byte[] buf = new byte[1024]; int l = 0; -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); while (oais.available() > 0) { l = oais.read(buf, 0, 1024); diff --git a/src/test/java/vavi/sound/sampled/adpcm/rhom/RohmAudioFileReaderTest.java b/src/test/java/vavi/sound/sampled/adpcm/rhom/RohmAudioFileReaderTest.java index 3117467..176c2f5 100644 --- a/src/test/java/vavi/sound/sampled/adpcm/rhom/RohmAudioFileReaderTest.java +++ b/src/test/java/vavi/sound/sampled/adpcm/rhom/RohmAudioFileReaderTest.java @@ -17,7 +17,6 @@ import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.SourceDataLine; import org.junit.jupiter.api.BeforeEach; @@ -29,6 +28,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -90,10 +90,7 @@ public void test1() throws Exception { line.start(); byte[] buf = new byte[1024]; int l = 0; -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); while (oais.available() > 0) { l = oais.read(buf, 0, 1024); diff --git a/src/test/java/vavi/sound/sampled/adpcm/vox/VoxAudioFileReaderTest.java b/src/test/java/vavi/sound/sampled/adpcm/vox/VoxAudioFileReaderTest.java index 38d189b..0d8f9a4 100644 --- a/src/test/java/vavi/sound/sampled/adpcm/vox/VoxAudioFileReaderTest.java +++ b/src/test/java/vavi/sound/sampled/adpcm/vox/VoxAudioFileReaderTest.java @@ -17,7 +17,6 @@ import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.SourceDataLine; import org.junit.jupiter.api.BeforeEach; @@ -28,6 +27,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -89,10 +89,7 @@ public void test1() throws Exception { line.start(); byte[] buf = new byte[1024]; int l = 0; -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); while (oais.available() > 0) { l = oais.read(buf, 0, 1024); diff --git a/src/test/java/vavi/sound/sampled/adpcm/yamaha/YamahaAudioFileReaderTest.java b/src/test/java/vavi/sound/sampled/adpcm/yamaha/YamahaAudioFileReaderTest.java index 9fea7d6..c9f29b0 100644 --- a/src/test/java/vavi/sound/sampled/adpcm/yamaha/YamahaAudioFileReaderTest.java +++ b/src/test/java/vavi/sound/sampled/adpcm/yamaha/YamahaAudioFileReaderTest.java @@ -17,7 +17,6 @@ import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; -import javax.sound.sampled.FloatControl; import javax.sound.sampled.SourceDataLine; import org.junit.jupiter.api.BeforeEach; @@ -28,6 +27,7 @@ import vavix.util.Checksum; import static org.junit.jupiter.api.Assertions.assertEquals; +import static vavi.sound.SoundUtil.volume; /** @@ -89,10 +89,7 @@ public void test1() throws Exception { line.start(); byte[] buf = new byte[1024]; int l = 0; -FloatControl gainControl = (FloatControl) line.getControl(FloatControl.Type.MASTER_GAIN); -double gain = .2d; // number between 0 and 1 (loudest) -float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0); -gainControl.setValue(dB); + volume(line, .2d); while (oais.available() > 0) { l = oais.read(buf, 0, 1024); diff --git a/src/test/java/vavi/sound/sampled/mfi/MfiAudioFileWriterTest.java b/src/test/java/vavi/sound/sampled/mfi/MfiAudioFileWriterTest.java index 1fb423b..6eb37ec 100644 --- a/src/test/java/vavi/sound/sampled/mfi/MfiAudioFileWriterTest.java +++ b/src/test/java/vavi/sound/sampled/mfi/MfiAudioFileWriterTest.java @@ -6,18 +6,20 @@ package vavi.sound.sampled.mfi; +import java.io.BufferedInputStream; import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; -import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.fail; - /** * MfiAudioFileWriterTest. @@ -25,12 +27,37 @@ * @author Naohide Sano (umjammer) * @version 0.00 2012/10/02 umjammer initial version
    */ -@Disabled public class MfiAudioFileWriterTest { + String nullDevice = System.getProperty("vavi.test.dev.null"); + + static Path dir; + + @BeforeAll + static void setup() throws Exception { + dir = Paths.get("tmp"); + if (Files.exists(dir)) { + Files.createDirectories(dir); + } + } + @Test - public void test() { - fail("Not yet implemented"); + public void test() throws Exception { + Path path = Paths.get(MfiAudioFileWriterTest.class.getResource("/mono.wav").toURI()); + AudioInputStream ais = AudioSystem.getAudioInputStream(new BufferedInputStream(Files.newInputStream(path))); +System.err.println(ais.getFormat()); + Map properties = new HashMap<>(); + properties.put("mfi.divided", true); + properties.put("mfi.directory", dir.toString()); + properties.put("mfi.base", path.getFileName().toString().replace(".wav", "_%d.mfi")); + properties.put("mfi.model", "sh900"); + properties.put("mfi.time", 10.0f); + properties.put("mfi.sampleRate", 8000); + properties.put("mfi.bits", 4); + properties.put("mfi.channels", 1); + properties.put("mfi.masterVolume", 100); + properties.put("mfi.adpcmVolume", 100); + AudioSystem.write(ais, new MFi(properties), new File(nullDevice)); } //---- diff --git a/src/test/java/vavi/sound/sampled/smaf/SmafAudioFileWriterTest.java b/src/test/java/vavi/sound/sampled/smaf/SmafAudioFileWriterTest.java index a8fef9d..d7aab02 100644 --- a/src/test/java/vavi/sound/sampled/smaf/SmafAudioFileWriterTest.java +++ b/src/test/java/vavi/sound/sampled/smaf/SmafAudioFileWriterTest.java @@ -6,18 +6,20 @@ package vavi.sound.sampled.smaf; +import java.io.BufferedInputStream; import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; -import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.fail; - /** * SmafAudioFileWriterTest. @@ -25,12 +27,57 @@ * @author Naohide Sano (umjammer) * @version 0.00 2012/10/02 umjammer initial version
    */ -@Disabled public class SmafAudioFileWriterTest { + String nullDevice = System.getProperty("vavi.test.dev.null"); + + static Path dir; + + @BeforeAll + static void setup() throws Exception { + dir = Paths.get("tmp"); + if (Files.exists(dir)) { + Files.createDirectories(dir); + } + } + + /** + * mono wave -> smaf + */ @Test - public void test() { - fail("Not yet implemented"); + public void test0() throws Exception { + Path path = Paths.get(SmafAudioFileWriterTest.class.getResource("/mono.wav").toURI()); + AudioInputStream ais = AudioSystem.getAudioInputStream(new BufferedInputStream(Files.newInputStream(path))); + Map properties = new HashMap<>(); + properties.put("smaf.divided", true); + properties.put("smaf.directory", dir.toString()); + properties.put("smaf.base", path.getFileName().toString().replace(".wav", "_%d.mmf")); + properties.put("smaf.time", (float) 10.0); + properties.put("smaf.sampleRate", 8000); + properties.put("smaf.bits", 4); + properties.put("smaf.channels", 1); + properties.put("smaf.masterVolume", 100); + properties.put("smaf.adpcmVolume", 100); + new SmafAudioFileWriter().write(ais, new SMAF(properties), new File(nullDevice)); + ais.close(); + } + + @Test + public void test1() throws Exception { + Path path = Paths.get(SmafAudioFileWriterTest.class.getResource("/mono.wav").toURI()); + AudioInputStream ais = AudioSystem.getAudioInputStream(new BufferedInputStream(Files.newInputStream(path))); + Map properties = new HashMap<>(); + properties.put("smaf.divided", true); + properties.put("smaf.directory", dir.toString()); + properties.put("smaf.base", path.getFileName().toString().replace(".wav", "_%d.mmf")); + properties.put("smaf.time", (float) 10.0); + properties.put("smaf.sampleRate", 8000); + properties.put("smaf.bits", 4); + properties.put("smaf.channels", 1); + properties.put("smaf.masterVolume", 100); + properties.put("smaf.adpcmVolume", 100); + AudioSystem.write(ais, new SMAF(properties), new File(nullDevice)); + ais.close(); } //---- @@ -56,7 +103,7 @@ public static void main(String[] args) throws Exception { properties.put("smaf.masterVolume", 100); properties.put("smaf.adpcmVolume", 100); AudioSystem.write(ais, new SMAF(properties), new File(nullDevice)); - System.exit(0); + ais.close(); } } diff --git a/src/test/java/vavi/sound/smaf/ChunkTest.java b/src/test/java/vavi/sound/smaf/ChunkTest.java index b14cd0e..36bb2a8 100644 --- a/src/test/java/vavi/sound/smaf/ChunkTest.java +++ b/src/test/java/vavi/sound/smaf/ChunkTest.java @@ -6,158 +6,13 @@ package vavi.sound.smaf; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import org.junit.jupiter.api.Test; - -import vavi.sound.smaf.chunk.Chunk; - -import static org.junit.jupiter.api.Assertions.assertEquals; - - /** * ChunkTest. * * @author Naohide Sano (nsano) * @version 0.00 050508 nsano initial version
    */ -public class ChunkTest { - - /** for testing protected methods */ - class HackedChunk extends Chunk { - - @Override - protected void init(InputStream is, Chunk parent) throws InvalidSmafDataException, IOException { - } - - public int readOneToFour(InputStream is) throws IOException { - return super.readOneToFour(is); - } - - public int readOneToTwo(InputStream is) throws IOException { - return super.readOneToTwo(is); - } - - @Override - public void writeTo(OutputStream os) throws IOException { - } - } - - /** for testing protected methods */ - class HackedMessage extends SmafMessage { - - /* */ - public void writeOneToFour(OutputStream os, int value) throws IOException { - super.writeOneToFour(os, value); - } - - /* */ - @Override - public void writeOneToTwo(OutputStream os, int value) throws IOException { - super.writeOneToTwo(os, value); - } - - @Override - public int getLength() { - return 0; - } - - @Override - public byte[] getMessage() { - return null; - } - } - - /** - * Tests {@link HackedChunk#readOneToFour(InputStream)}. - *
    -     *  実際の数値 | 可変長での表現
    -     * ------------+-------------
    -     *  00000000   | 00
    -     *  00000040   | 40
    -     *  0000007F   | 7F
    -     *  00000080   | 81 00
    -     *  00002000   | C0 00
    -     *  00003FFF   | FF 7F
    -     *  00004000   | 81 80 00
    -     *  00100000   | C0 80 00
    -     *  001FFFFF   | FF FF 7F
    -     *  00200000   | 81 80 80 00
    -     *  08000000   | C0 80 80 00
    -     *  0FFFFFFF   | FF FF FF 7F
    -     * 
    - */ - @Test - public void testReadOneToFour() throws Exception { - HackedChunk chunk = new HackedChunk(); - assertEquals(0x00000000, chunk.readOneToFour(new ByteArrayInputStream(new byte[] { 0x00 }))); - assertEquals(0x00000040, chunk.readOneToFour(new ByteArrayInputStream(new byte[] { 0x40 }))); - assertEquals(0x0000007F, chunk.readOneToFour(new ByteArrayInputStream(new byte[] { 0x7F }))); - assertEquals(0x00000080, chunk.readOneToFour(new ByteArrayInputStream(new byte[] { (byte) 0x81, 0x00 }))); - assertEquals(0x00002000, chunk.readOneToFour(new ByteArrayInputStream(new byte[] { (byte) 0xC0, 0x00 }))); - assertEquals(0x00003FFF, chunk.readOneToFour(new ByteArrayInputStream(new byte[] { (byte) 0xFF, 0x7F }))); - assertEquals(0x00004000, chunk.readOneToFour(new ByteArrayInputStream(new byte[] { (byte) 0x81, (byte) 0x80, 0x00 }))); - assertEquals(0x00100000, chunk.readOneToFour(new ByteArrayInputStream(new byte[] { (byte) 0xC0, (byte) 0x80, 0x00 }))); - assertEquals(0x001FFFFF, chunk.readOneToFour(new ByteArrayInputStream(new byte[] { (byte) 0xFF, (byte) 0xFF, 0x7F }))); - assertEquals(0x00200000, chunk.readOneToFour(new ByteArrayInputStream(new byte[] { (byte) 0x81, (byte) 0x80, (byte) 0x80, 0x00 }))); - assertEquals(0x08000000, chunk.readOneToFour(new ByteArrayInputStream(new byte[] { (byte) 0xC0, (byte) 0x80, (byte) 0x80, 0x00 }))); - assertEquals(0x0FFFFFFF, chunk.readOneToFour(new ByteArrayInputStream(new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, 0x7F }))); - } - - /** - * Tests {@link HackedChunk#readOneToTwo(InputStream)}. - *
    -     *  実際の数値 | 可変長での表現
    -     * ------------+-------------
    -     *  00000000   | 00
    -     *  00000040   | 40
    -     *  0000007F   | 7F
    -     *  00000081   | 80 01
    -     *  00000100   | 81 00
    -     *  00002000   | C0 00
    -     *  0000407F   | FF 7F
    -     * 
    - */ - @Test - public void testReadOneToTwo() throws Exception { - HackedChunk chunk = new HackedChunk(); - assertEquals(0x00000000, chunk.readOneToTwo(new ByteArrayInputStream(new byte[] { 0x00 }))); - assertEquals(0x00000040, chunk.readOneToTwo(new ByteArrayInputStream(new byte[] { 0x40 }))); - assertEquals(0x0000007F, chunk.readOneToTwo(new ByteArrayInputStream(new byte[] { 0x7F }))); - assertEquals(0x00000081, chunk.readOneToTwo(new ByteArrayInputStream(new byte[] { (byte) 0x80, 0x01 }))); - assertEquals(0x00000100, chunk.readOneToTwo(new ByteArrayInputStream(new byte[] { (byte) 0x81, 0x00 }))); - assertEquals(0x00002080, chunk.readOneToTwo(new ByteArrayInputStream(new byte[] { (byte) 0xC0, 0x00 }))); - assertEquals(0x0000407F, chunk.readOneToTwo(new ByteArrayInputStream(new byte[] { (byte) 0xFF, 0x7F }))); - } - - /** - * Tests {@link SmafMessage#writeOneToTwo(OutputStream, int)}. - */ - @Test - public void test01() throws Exception { - assertEquals(15000 / 4, wr(15000 / 4)); - assertEquals(0x0040, wr(0x0040)); - assertEquals(0x007f, wr(0x007f)); - assertEquals(0x0080, wr(0x0080)); - assertEquals(0x2000, wr(0x2000)); - assertEquals(0x3fff, wr(0x3fff)); - } - - /** - * {@link SmafMessage#writeOneToTwo(OutputStream, int)} - */ - private int wr(int v) throws Exception { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - HackedMessage message = new HackedMessage(); - message.writeOneToTwo(baos, v); - ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - HackedChunk chunk = new HackedChunk(); - return chunk.readOneToTwo(bais); - } +class ChunkTest { } /* */ diff --git a/src/test/java/vavi/sound/smaf/SmafFileFormatTest.java b/src/test/java/vavi/sound/smaf/SmafFileFormatTest.java index 41dbddb..c5c3638 100644 --- a/src/test/java/vavi/sound/smaf/SmafFileFormatTest.java +++ b/src/test/java/vavi/sound/smaf/SmafFileFormatTest.java @@ -8,12 +8,13 @@ import java.io.BufferedInputStream; import java.io.FileInputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.fail; - /** * SmafFileFormatTest. @@ -21,12 +22,12 @@ * @author Naohide Sano (umjammer) * @version 0.00 2012/10/02 umjammer initial version
    */ -@Disabled public class SmafFileFormatTest { @Test - public void test() { - fail("Not yet implemented"); + public void test() throws Exception, IOException { + Path path = Paths.get(SmafFileFormatTest.class.getResource("/test.mmf").toURI()); + SmafSystem.getSmafFileFormat(new BufferedInputStream(Files.newInputStream(path))); } //---- @@ -37,7 +38,6 @@ public void test() { */ public static void main(String[] args) throws Exception { SmafSystem.getSmafFileFormat(new BufferedInputStream(new FileInputStream(args[0]))); - System.exit(0); } } diff --git a/src/test/java/vavi/sound/smaf/SmafSystemTest.java b/src/test/java/vavi/sound/smaf/SmafSystemTest.java index f0d7ccd..3397689 100644 --- a/src/test/java/vavi/sound/smaf/SmafSystemTest.java +++ b/src/test/java/vavi/sound/smaf/SmafSystemTest.java @@ -9,17 +9,18 @@ import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.concurrent.CountDownLatch; import javax.sound.midi.MidiSystem; import javax.sound.midi.Sequence; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import vavi.util.Debug; -import static org.junit.jupiter.api.Assertions.fail; - /** * SmafSystemTest. @@ -27,12 +28,25 @@ * @author Naohide Sano (umjammer) * @version 0.00 2012/10/02 umjammer initial version
    */ -@Disabled public class SmafSystemTest { @Test - public void test() { - fail("Not yet implemented"); + public void test() throws Exception { + CountDownLatch cdl = new CountDownLatch(1); + Path inPath = Paths.get(SmafSystemTest.class.getResource("/test.mmf").toURI()); + Sequencer sequencer = SmafSystem.getSequencer(); + sequencer.open(); + vavi.sound.smaf.Sequence sequence = SmafSystem.getSequence(new BufferedInputStream(Files.newInputStream(inPath))); + sequencer.setSequence(sequence); + sequencer.addMetaEventListener(meta -> { +Debug.println(meta.getType()); + if (meta.getType() == 47) { + cdl.countDown(); + } + }); + sequencer.start(); + cdl.await(); + sequencer.close(); } //------------------------------------------------------------------------- diff --git a/src/test/java/vavi/sound/smaf/message/SmafContextTest.java b/src/test/java/vavi/sound/smaf/message/SmafContextTest.java index d6c042e..dd387b2 100644 --- a/src/test/java/vavi/sound/smaf/message/SmafContextTest.java +++ b/src/test/java/vavi/sound/smaf/message/SmafContextTest.java @@ -6,20 +6,23 @@ package vavi.sound.smaf.message; +import java.io.BufferedInputStream; import java.io.File; import java.io.FileOutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import javax.sound.midi.MidiFileFormat; import javax.sound.midi.MidiSystem; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import vavi.sound.smaf.SmafSystem; import vavi.util.Debug; -import static org.junit.jupiter.api.Assertions.fail; - /** * SmafContextTest. @@ -27,12 +30,31 @@ * @author Naohide Sano (umjammer) * @version 0.00 2012/10/02 umjammer initial version
    */ -@Disabled public class SmafContextTest { + static Path dir; + + @BeforeAll + static void setup() throws Exception { + dir = Paths.get("tmp"); + if (Files.exists(dir)) { + Files.createDirectories(dir); + } + } + @Test - public void test() { - fail("Not yet implemented"); + @Disabled("not implemented yet") + public void test() throws Exception { + Path inPath = Paths.get(SmafContextTest.class.getResource("/test.mid").toURI()); + javax.sound.midi.Sequence midiSequence = MidiSystem.getSequence(new BufferedInputStream(Files.newInputStream(inPath))); + MidiFileFormat midiFileFormat = MidiSystem.getMidiFileFormat(new BufferedInputStream(Files.newInputStream(inPath))); + int type = midiFileFormat.getType(); +Debug.println("type: " + type); + vavi.sound.smaf.Sequence smafSequence = SmafSystem.toSmafSequence(midiSequence, type); + + Path outPath = dir.resolve("SmafContextTest.mmf"); + int r = SmafSystem.write(smafSequence, 0, Files.newOutputStream(outPath)); +Debug.println("write: " + r); } //------------------------------------------------------------------------- diff --git a/src/test/resources/logging.properties b/src/test/resources/logging.properties index 65e7685..6e1b800 100644 --- a/src/test/resources/logging.properties +++ b/src/test/resources/logging.properties @@ -1,7 +1,7 @@ handlers=java.util.logging.ConsoleHandler -.level=INFO +.level=ALL # Limit the message that are printed on the console to INFO and above. -java.util.logging.ConsoleHandler.level=INFO +java.util.logging.ConsoleHandler.level=ALL #java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter # %1:date/time %2:className and methodName %3logName %4:level %5:message %6:errormessage #java.util.logging.SimpleFormatter.format=%1$tY/%1$tm/%1$td %1$tH:%1$tM:%1$tS.%1$tL [%4$s] %5$s %6$s%n @@ -9,6 +9,7 @@ java.util.logging.ConsoleHandler.level=INFO # HttpUrlConnection #java.util.logging.ConsoleHandler.level=ALL #sun.net.www.protocol.http.HttpURLConnection.level=ALL +org.junit.level=INFO java.util.logging.ConsoleHandler.formatter=vavi.util.logging.VaviFormatter #java.util.logging.ConsoleHandler.formatter=vavi.util.logging.BetterFormatter diff --git a/src/test/resources/mono.wav b/src/test/resources/mono.wav new file mode 100644 index 0000000..850daf2 Binary files /dev/null and b/src/test/resources/mono.wav differ diff --git a/src/test/resources/test.mid b/src/test/resources/test.mid new file mode 100644 index 0000000..9a8fb31 Binary files /dev/null and b/src/test/resources/test.mid differ diff --git a/src/test/resources/test.mld b/src/test/resources/test.mld new file mode 100644 index 0000000..b6104e8 Binary files /dev/null and b/src/test/resources/test.mld differ diff --git a/src/test/resources/test.mmf b/src/test/resources/test.mmf new file mode 100644 index 0000000..c7662de Binary files /dev/null and b/src/test/resources/test.mmf differ diff --git a/src/test/resources/vavi/sound/adpcm/ccitt/out.vavi.4.adpcm b/src/test/resources/vavi/sound/adpcm/ccitt/out.vavi.4.adpcm deleted file mode 100644 index cd557af..0000000 --- a/src/test/resources/vavi/sound/adpcm/ccitt/out.vavi.4.adpcm +++ /dev/null @@ -1 +0,0 @@ -rgQF$?RK<2/fSܟ,t/~2ѝF3B!5BUk}#Y=J#{=_$2bN[#"!ﭭJOUO4FBJ/,;Un+L:1_MBS"y-",\qtb*nT5+Bӱ2~^\|2osN-}>ݲlT_Fi*/;3̾ReQ5ab#R#"NGOT=c~5[~ZjQXÕ,;Yb+B!8)M-!L[3#aM4\"ӿiL"M&KN߭oM%SM.4D_.!?Q'23#O+^?N|;=ɻӯMcc,2)>C=!%3../L5$ZٮNC,/EU-C9,L!ͼKU\+N43.!3">AK̹NB!#.4K>$A+>qݢO24ޱL$$b3!T$95Om*+r£|>3߹2=TT&Sκb1RR."291#"+/3.-6B&5M:KNE?ܿS6zNj.>lR~!*Y/COc>D-NN=R/BBϛTA9~BJ>a""#"Z5n/4/3%NQ>R%?CC==o3S!~^$4L2a!J^CޯA4qR7I-|]4D߼]!˚+U.###T].ޫ.#$2i_"6NUO"9$=*;!}nQ?*!%QNL"%콃=%-"һ6Qͽ<+,E?/+K2D;)nQ'ړoR6̽_ށN1So;4=K!6T_Ҭ5C%˂*KC$QK\33<:AA2ѫ?'۟B[~8Az1.aѾ:A-!12!2lԳ+SmbBa/1>b/]Q2NT?.>>3B>'ͫQ,Dĩ]6횽M[Rc#aŋo:C2;E(/jYZL9LQY&*Աn,Nb"+%.LCUAk+F,V_O!ī^4'1!,N,ۺѿ9/b>*4%Qd-3(An/UD-c2T%)^of#n͹lRq/s22C3ݱ̭%'B?-7޼+"ΪCf.!AQ>Ld95'~!ާR:Jkє3A#O>_\o/5";R3T:=<ϥA.bn#A38,O^E?b$a&ܩ>o+]TaCo2TJ/ī8?-\$o5tUݮjËΥA,M/aS-?KD\2.2_$33.nT+?ou!OT52!~LO3%Aޢ>3U"΢ͳ,{_=̥\궲2-Le%=<ʵ~.E^S?B421=B?.ku%-6!U:CA6C-/C1ۜAay56"LK&T\Viųzj~*E=%Z9ZA,^R_D#Z4j^?Qm]nA6Y.̤9ޝ֣C3ղIO$+Ϟ,#-MD+1N<:aBF=nuJ!޺-6:_ec_s^M3OE9::eNS"CF/D+O7BEB/M66ڿ,CCR3]A,/Z:&^lOyi[M,c._"N2JZޢ!V>"/TɿR!#/E9S[^|?#ʿ6LS!=#\S%.QOz>͚mLQ1+>.!">T.AD^12A.έn'ACAF"l,/B4n.#S锾+$"$5-?~.޾/\%9(sM=LQBt/Nñ-&2#C"NS;_a2U1M?6}1,ڲC^?=;6ᜱ}#B(!2>n*:2d˃/O%RB-m^kJ.a4]Kz1޼^oO\Į"B!ܬA_~/"A%/-J"6\\o#J5TMSݱ!S|C12=$oZ/]nIn<3El45*nEQ,AO#1#Bd1"!1.LR.>ܞ#3&1Aa4=βna]?^=zAT#*oU_NUAQ5"4oo2Ο-$$O*/2&oNe-:CM#5>\_5ܡ2Rb.4!;|;.AݛaE.!S4/c1<3ɄMA>5,^O1!%"N#4Ŷ'E>}>COR.ߑ#2ӟ6>#^2M#;5|L;+"8<];o>,]*>=O:43.m%!?5tA6.OS?>T+C"S6/o'"ߛBEͼAsOC..BBܻS2$?=Ꞿ.Lc1Q#}.NNo!Y.#C2?}+7,/<.m^<_Am\?T=sSڋS$E6c#}.?f51[R>IJ29՜ű$mԑ{3{=!]_:!^.&?!>3F/QkBZ1>-JB{%Ų>A׭IJb=MJTMAM^_o,^-5%BBQq.o_bQOO_!E×#&l=2$!-kC5_dL+&b*U1D͹NT#N.OB$ߪ1UVCߞ*'A#2#U2U깪[=?L,꟡J9Am3~=>ݑbN]3R\>R4$M_ܸ&D4Ls1M/"3S6›WF".čӤƿ"1#,!1#Վ/3-2_ڒU$>)B1>_.N'163-D$^R$ν"T$'۫-A,ڽI1^_M4!;.=/aL>^򒒣6!^$ݳD3$ޱDqJ9b-YE4S![m/Nc?]oS!K2_52N2DA#!;M>%{哱#%’1Q,բ-nN5α̤I_2n3"%%=T"/MB/1ܲ*d4RA.s%#b?۱,%A*OC$z"ak_=$2NQA8ABC$O!.7,Qo^O1ͭm㮿q?CNQϮb.]?=6<4_>*3lkI$AN;i2m.&/}AQ.Ja4d^-?ѿO1%tߒa2="A-j_><"R-+F3[,s%!a"a#"}L"á1ij/2_Yͱ)䲢=4ҳ+4?+4RQ1q+a21K_1?*^uO#E3"34/<TD=U24#!3˼S'!3T#3!ͻn.4T޽٪"1oBD-A1D_M.2Z>>=M"o[_C-C\ҳ",1>)3.#1b%ZG8$Y\#ҳ[#eS2A6R/3r/?T2a2ŒO"tAQq1O:Ņſх/,+;E2_A,"?OC.AA_Nc-..2.B#/K15>j?b9%1|R5["E6!!6$L'֟omF94^ս$)[>A絫OL>DԵBMӺBA1ӏA>BDM2C2#a2YܴN?!#J3O4!_."A"$,/e4!!3=1\"ߴ/4®.A#-3QR2/N2>SOj><3(#=A>L2"/?2^n=;.#1"!ӏ5ߑNQ$]"+}K2J$ϻ&,N"5Rc"T$jQ.N2o:-2D#&?MQ"K$cAO!M$N1"3;=B5=Q>O$.!<5:!A/O#+_>mR2Os?)"BDN"3Nb.Z&BQa/=O-8O-""+q/=O"M2.>#B-?"<a?A$#"O$/>"=K"ÿ#5CnN>1Z_L?5?,M"B3ConD2Ү&Kd*2(QZlKBn[?2߁RDM*QL\J>^),o\A/+o312,%=%%####/>e/QOm-j\S_B|SA+"#BoSIi{{OL,O12d=S=ޢ"56!B6ӭT;?!!.+/<#.=Qr?Ldѵ4fB(,];B,+R,N2)B>LR:BCӛM/cFC2AD3Fc!]SZER-BV5H!3{-38<->Q#4?>NN}?.^>(]1RJ:|/1"£A%Bﯝ*6R1EEo1LQE.I5;M*?l{"NB\Ej\/=mM;;˺l1B?HB-3%>63BEDNV3B44+!/353BVC=K.\/o5>)<1C?>^&+=CCA?o1=2M+6#bm?!A-/K%A+~;#!A,O-1r"$11R弋>$?rB12-#3c-(^Ⓜ8!]>=^8/A8jO$L,"?Q1^_A11RQ^bA1Oo-_Q*.A;T11Zmq-.Z.SnJ5D+Z2]_+?)S3\.:THD}2|2s3ŏ%&D,5M,;R[N]A!VKFI5>[o3\12ҩ3B1k?]M"SY4m>"Un1CjO!Ta6o.4Z\Cj4o]K2\\BiS)4]!m4YZ3CZAYIn|l=y^!q^!"{[l34#֓[%Ҟ4&1K&5/­5ND8/2aJ$bn!Fo.Bc]BoyDn>dnCH._z/A%oOCn#jO3Oӝ2lm#k4㜦?OşNەOOŏ.LѵNʢﬣLM=Kn_=n.lm-l/]I_oCs>2R/ao"a82]2IbQ.3m^Kk"iB"QѩMρ?ˮRĩÒґsMB$>ev"SO/>qa?(>oO1o^#b;ak4#n!?&!2Ƣ.\ʴ/9%{MZ;+#*6[&UJ)1'$ֳf2bb(d>Erc["aq?=i3!Ғ,ԑLϑ]!J]!=.2"߃Ă]ң>Lr"Qb1cnn$rnR4jS"jBK!ł+<9=9=/e\FA[FDlE\"$.܍\L(k_n]LF\KUb]TnQk3#IҪB>"l2q^31}>!?>}"Q-YE]2Z.U1%nŠRϚϣCb$^V565Mn>KQCna3Q]qӜ_aaҭ^oңlζ,5655E#Q:O\_[m_R\1?M}A<*?>E53>2bE4οO/cUK{C!o#\B3-N1Q%:mJ3KOԍִܶC3"#DCA"/?s4!O5cA'CT"Mo)a#܃^+>ԋ3#|.>(M^]("("M!/"",yB#3?:\95}4\ӣ/+T/N2~ϟ%/6E۳4B6j\^_&r3*+Q+%SCªNVBEFD#DK3T37ﳪ2$55N&2#/_=BAD$$Znı1$sōbM"r1$>#˹DBTSn5oݹcF1ou4:%ӼtD!mRYs,>ByyL/jk=3Z1!KJ>_)B[?1=O?BQY1Oν'!*.cOR+E;^mao+%9&~,U%KլM$ߵ'(Z#J$A<])cϻT22$*c$\!NnOc#e|An\8?O!O2oKi?,BR/]n=M(aK^KCJ<5D~O#O.?Ӫ3!22b6~.2JN?)AQl?(6aBBO^Ý"dB(2Aoob!A;,+DF5T1DR-B2r"RAB"3(Q?_N:-ORADS_Ca^AJNSB_>_-_L^O)B>/2?ONB/~.A2_"O.M2BJ3_32Q/D_/QR!>c?5?"?>?T3Nc1^m'/#֌F$$DSD$%%%%%3-$Қ64RN$$A&$+3݃^ބKý542Bt.q?5B:3}Q"~3]S/nCLB1.^d/Na~nMD)Nd*RcKa[a*L^]_&)_UQT?SNQMAM?;Q?:RCb>%?]R.!/>Q/=QA3~>5kM2HO.>"MmBL^O=Q[-AO#B23bA=S!+CO3>43Tc"4,43C2$4DTcR$2CDSA"_3^B=]_ZMNY/]J?MIQk1]Qocӽ=%""=&S634.26-U6SS!R))>./=B/+?bON"NN1-VUC3>!_C2,AT%&T?+>42ߥ>1$#%4%![FA5.[̯䂽RҍR_U2>U%ّ11:;!T5%T!52ʋ}#&ϩ"Oq"m"Ob?A3>a*oO"jNMB>ANQޮ##‘,#O.)ڏ]R/%m2n4N_5_K.<[ZQ_/nmoNOE<:FӺ(Q1!-#߁MdVL+O'q$.>NRҪ=TO3Od.-/>1Q랹Lt"ѿ3445/S#$q.,l1ڳM2<>Aam3c-S;{^o>Q?m~-~K!3޴A5>3r/犯M33Me2Mdon߹|31?˩?BnT,4a}.!#*A>{/1{ZY^m[AYLM=."AL12=<]2c>kC1ă,4杴ֺԯ̶ԳÝ*=3"4%L5۲"+?#>MBr;4S(.>9Ao1e^=/N=^"D[$nLAN&eV.-"?,,^Z#1N2'=}/}/)"41_tűb!q!bOƬſ4޶$ƽ#DҢLܢ̾555%Qm"2CTOTO'ʓe2EKO#on5m/!,/=[[j.O.R-BC_4o;FQ!DQ6bk2$?a":+3*B)B1Qq#-}](n>D{>.1*>>bkM3/1;m_N.CI4?EK\:;<(M<6j-f/=>'!FqA^QTLo]Nds?OM,JF$2R3ԫ$%%?$C<$ʱ">qn&nD#ocn"8AAAAM]:>/;NODz>%>;A%KO_V;b6C)1M]-M9No-[;{/,~",o>N!=AaLQ>(A,MN}1?!!O/RMN_B-.1,m)Cr!>rMOD.>uMOb-RRTN\o^aL;[~[=aQ_{>/:UQrR)-BRR߬E'Ԓs9}/O%TfB?$ž%Ԯ%$Ҿÿ!"CF#3D52ϼ4E"^bd3˽$ܡC*ec5bOlšm.n,*|=>CK?>bM/1q=?/[o1%?1o!EST!5#E5֭V%BսB$V';#O[z<]/9>-D=>4[N4*2LQ=oi2ҭK]T35/?##ѡ1"#ÍcSFt;Q|.+o*,T)]|?MA_L?_oO_oMMbN6#&ݞ|\-߁N<3CaB[%S+UAD2f"AN3t!>.VD4"C#㱟ϣ#ԽTS)#AͪQ+4q.1L2]1O*n$&%=<2L]-",1"B-B'5}_Ì/=R5$A4$D̚Rb"B'Ec/>D$OYT]Ԍ1}aJ^]8;-?{>;^/A;/T/QB3$#<.43]3+MԜ$A%2!%?AON5N_2o;CoNRZOn2<^K,/K1_ME$#6:֖=2%#31q/$(<;$ô|"N$b4,TAERU"?EC'"4ξO4D?ϡDlbj..*Q)O"V~>#MA]]B_Sl_(>\!ݱ)T_R'>^OaqҬ!ɿ=">c&?⣽>&I6TB"3^"+&>:4-4)&b:UaEb;Ҽ½/δUDļ4Բ%.4Ub3$&2>3&dcST^:҃9Ԝ,ER.Tґ55!&vDcɒRȖb2Oպdm._b##cObnD_/c!QK,(!9B4$c8OR>N#A1%|.#*2KN:q2Nڎ1m^9Z#k#䵮CÝ4A1T|!EEڱ1##&>1T"5ߣ?ؑBEQB&s\"s%A^_2MB9nO%bNF{MD.*Q3;L\54<]^)L"8b=ON-DL-1>?1M_^/!o2,LT/MSOMlTNAK9K,):fN!.vDVc=VaLBc?YAOBM[C]k,7Z!.f:fDQ?Q%l1EO/>O+[T"*R*1cM5*&q6&t#Ba£9ý*䎴EUd#a/˓<䩯$ɮ$/r}}"}!l?A4ɽN>.>JON;:O?.Q2L/\6KRE,mb=a,B|-MSKM"?>NM=C=Q/*}K)5ZL5q!NS/CL>,-N2һ+S.,QѻBb&OaT1T&R)4)?B"_%#Bb?R_A];B;R>q4M$L.O*CN1n \ No newline at end of file diff --git a/src/test/resources/vavi/sound/adpcm/ccitt/out.vavi.4.pcm b/src/test/resources/vavi/sound/adpcm/ccitt/out.vavi.4.pcm deleted file mode 100644 index 9393968..0000000 Binary files a/src/test/resources/vavi/sound/adpcm/ccitt/out.vavi.4.pcm and /dev/null differ diff --git a/src/test/resources/vavi/sound/adpcm/dvi/out.vavi.pcm b/src/test/resources/vavi/sound/adpcm/dvi/out.vavi.pcm deleted file mode 100644 index c06900c..0000000 Binary files a/src/test/resources/vavi/sound/adpcm/dvi/out.vavi.pcm and /dev/null differ diff --git a/src/test/resources/vavi/sound/adpcm/ma/out.vavi.adpcm b/src/test/resources/vavi/sound/adpcm/ma/out.vavi.adpcm deleted file mode 100644 index 7db9ca7..0000000 Binary files a/src/test/resources/vavi/sound/adpcm/ma/out.vavi.adpcm and /dev/null differ diff --git a/src/test/resources/vavi/sound/adpcm/ma/out.vavi.pcm b/src/test/resources/vavi/sound/adpcm/ma/out.vavi.pcm deleted file mode 100644 index dda7022..0000000 Binary files a/src/test/resources/vavi/sound/adpcm/ma/out.vavi.pcm and /dev/null differ diff --git a/src/test/resources/vavi/sound/adpcm/ms/out_vavi.adpcm b/src/test/resources/vavi/sound/adpcm/ms/out_vavi.adpcm deleted file mode 100644 index 397ffea..0000000 Binary files a/src/test/resources/vavi/sound/adpcm/ms/out_vavi.adpcm and /dev/null differ diff --git a/src/test/resources/vavi/sound/adpcm/oki/out.vavi.adpcm b/src/test/resources/vavi/sound/adpcm/oki/out.vavi.adpcm deleted file mode 100644 index 20afce5..0000000 Binary files a/src/test/resources/vavi/sound/adpcm/oki/out.vavi.adpcm and /dev/null differ diff --git a/src/test/resources/vavi/sound/adpcm/oki/out.vavi.pcm b/src/test/resources/vavi/sound/adpcm/oki/out.vavi.pcm deleted file mode 100644 index 530f66f..0000000 Binary files a/src/test/resources/vavi/sound/adpcm/oki/out.vavi.pcm and /dev/null differ diff --git a/src/test/resources/vavi/sound/adpcm/rohm/out.vavi.adpcm b/src/test/resources/vavi/sound/adpcm/rohm/out.vavi.adpcm deleted file mode 100644 index 9aaa532..0000000 Binary files a/src/test/resources/vavi/sound/adpcm/rohm/out.vavi.adpcm and /dev/null differ diff --git a/src/test/resources/vavi/sound/adpcm/rohm/out.vavi.pcm b/src/test/resources/vavi/sound/adpcm/rohm/out.vavi.pcm deleted file mode 100644 index 250f882..0000000 Binary files a/src/test/resources/vavi/sound/adpcm/rohm/out.vavi.pcm and /dev/null differ diff --git a/src/test/resources/vavi/sound/adpcm/vox/out.vavi.adpcm b/src/test/resources/vavi/sound/adpcm/vox/out.vavi.adpcm deleted file mode 100644 index e005ce9..0000000 Binary files a/src/test/resources/vavi/sound/adpcm/vox/out.vavi.adpcm and /dev/null differ diff --git a/src/test/resources/vavi/sound/adpcm/vox/out.vavi.pcm b/src/test/resources/vavi/sound/adpcm/vox/out.vavi.pcm deleted file mode 100644 index 4a0d8bb..0000000 Binary files a/src/test/resources/vavi/sound/adpcm/vox/out.vavi.pcm and /dev/null differ diff --git a/src/test/resources/vavi/sound/adpcm/yamaha/out.vavi.adpcm b/src/test/resources/vavi/sound/adpcm/yamaha/out.vavi.adpcm deleted file mode 100644 index bea4afc..0000000 Binary files a/src/test/resources/vavi/sound/adpcm/yamaha/out.vavi.adpcm and /dev/null differ diff --git a/src/test/resources/vavi/sound/adpcm/yamaha/out.vavi.pcm b/src/test/resources/vavi/sound/adpcm/yamaha/out.vavi.pcm deleted file mode 100644 index 1d58c62..0000000 Binary files a/src/test/resources/vavi/sound/adpcm/yamaha/out.vavi.pcm and /dev/null differ diff --git a/src/test/resources/vavi/sound/adpcm/ym2608/out_vavi.adpcm b/src/test/resources/vavi/sound/adpcm/ym2608/out_vavi.adpcm deleted file mode 100644 index 19264fe..0000000 Binary files a/src/test/resources/vavi/sound/adpcm/ym2608/out_vavi.adpcm and /dev/null differ diff --git a/src/test/resources/vavi/sound/adpcm/ym2608/out_vavi.pcm b/src/test/resources/vavi/sound/adpcm/ym2608/out_vavi.pcm deleted file mode 100644 index 60375da..0000000 Binary files a/src/test/resources/vavi/sound/adpcm/ym2608/out_vavi.pcm and /dev/null differ