diff --git a/core/src/main/java/marumasa/marumasa_sign/core/SelfTest.java b/core/src/main/java/marumasa/marumasa_sign/core/SelfTest.java index 276c9cf..fc91919 100644 --- a/core/src/main/java/marumasa/marumasa_sign/core/SelfTest.java +++ b/core/src/main/java/marumasa/marumasa_sign/core/SelfTest.java @@ -95,9 +95,18 @@ void onLookup(boolean found) { // 読み込みが完了した看板が描画されたとき void onDrawn(SignImage image) { final String url = expectedUrl; - if (url != null && url.equals(image.spec.url)) drawnCount++; + if (url != null && url.equals(image.spec.url)) { + drawnCount++; + drawnImage = image; + } } + // 確認中の看板として最後に描画されたもの + private volatile SignImage drawnImage; + // 動画や音声の看板で、正面を向いているときの音の大きさ + private float facingGain; + private int facingDrawn; + private void next(int nextStep) { step = nextStep; ticksInStep = 0; @@ -208,8 +217,28 @@ private void run() { // 次に、看板そのものが消えていることを確認できるように、看板の位置を見下ろす if (ticksInStep >= 60 && ticksInStep < 140) platform.selfTestLook(50f); if (ticksInStep == 90) writeFile("sign-view-" + index + ".txt", "ready\n"); - if (ticksInStep >= 140) platform.selfTestLook(0f); - if (ticksInStep == 150) { + if (ticksInStep >= 140 && ticksInStep < 150) platform.selfTestLook(0f); + // 動画や音声の看板では、真上を向いて看板が視界から外れても、音が大きくならないことを確かめる + final SignImage image = drawnImage; + final float gain = image == null ? -1f : image.textureEntry().mediaGain(); + if (ticksInStep == 150 && gain >= 0) { + facingGain = gain; + facingDrawn = drawnCount; + } + final boolean checkGain = facingDrawn > 0; + if (checkGain && ticksInStep >= 150 && ticksInStep < 190) platform.selfTestLook(-90f); + if (checkGain && ticksInStep >= 190) platform.selfTestLook(0f); + if (checkGain && ticksInStep == 190) { + if (summary.length() > 0) summary.append(", "); + summary.append(String.format(java.util.Locale.ROOT, "%s volume facing %.3f, looking away %.3f (drawn %d times while away)", + new File(images[index]).getName(), facingGain, gain, drawnCount - facingDrawn)); + if (gain > facingGain + 0.01f) { + finish(false, summary + ": louder when looking away"); + return; + } + } + if (ticksInStep == (checkGain ? 200 : 150)) { + facingDrawn = 0; if (summary.length() > 0) summary.append(", "); summary.append(new File(images[index]).getName()).append(" rendered ").append(drawnCount).append(" times"); if (index + 1 < images.length) { diff --git a/core/src/main/java/marumasa/marumasa_sign/core/sign/MediaSession.java b/core/src/main/java/marumasa/marumasa_sign/core/sign/MediaSession.java index f6206a3..ad964a0 100644 --- a/core/src/main/java/marumasa/marumasa_sign/core/sign/MediaSession.java +++ b/core/src/main/java/marumasa/marumasa_sign/core/sign/MediaSession.java @@ -40,6 +40,10 @@ interface Listener { // この tick の間に描画された看板のうち、最も近いものまでの距離 private double nearestDistance = Double.MAX_VALUE; + // 最後に分かった、最も近い看板までの距離。 + // 看板が視界の外にあると描画されず距離が分からないので、その間はこの値で音量を決める + private double lastDistance = Double.MAX_VALUE; + private float currentGain; MediaSession(Platform platform, String url, Listener listener) { this.platform = platform; @@ -118,13 +122,30 @@ void tick() { player = null; return; } - // 近いほど大きく聞こえるようにする - final double distance = nearestDistance == Double.MAX_VALUE ? 0 : nearestDistance; - final double falloff = Math.max(0.0, 1.0 - distance / HEARING_DISTANCE); - player.setGain((float) (falloff * falloff * MarumaSign.config().getVolume() / 100.0)); + // 近いほど大きく聞こえるようにする。 + // 看板に背を向けると描画されなくなるが、そのときに距離 0 (最大音量) と見なさないよう、前の距離を使う + if (nearestDistance != Double.MAX_VALUE) lastDistance = nearestDistance; + currentGain = gain(lastDistance, MarumaSign.config().getVolume()); + player.setGain(currentGain); nearestDistance = Double.MAX_VALUE; } + // 今の音の大きさ (0 - 1)。再生していなければ -1 + float currentGain() { + return player == null ? -1f : currentGain; + } + + /** + * 看板までの距離と設定の音量から、再生する音の大きさ (0 - 1) を求める。 + * + * @param distance 看板までの距離 (ブロック)。分からなければ Double.MAX_VALUE で、音は出さない + * @param volume 設定の音量 (0 - 100) + */ + static float gain(double distance, int volume) { + final double falloff = Math.max(0.0, 1.0 - distance / HEARING_DISTANCE); + return (float) (falloff * falloff * volume / 100.0); + } + void close() { if (player != null) { player.stop(); diff --git a/core/src/main/java/marumasa/marumasa_sign/core/sign/TextureEntry.java b/core/src/main/java/marumasa/marumasa_sign/core/sign/TextureEntry.java index 865bdbe..4b5138d 100644 --- a/core/src/main/java/marumasa/marumasa_sign/core/sign/TextureEntry.java +++ b/core/src/main/java/marumasa/marumasa_sign/core/sign/TextureEntry.java @@ -75,6 +75,11 @@ MediaSession media() { return media; } + // 動画や音声の今の音の大きさ (0 - 1)。動画や音声でないか、再生していなければ -1 + public float mediaGain() { + return media == null ? -1f : media.currentGain(); + } + public int state() { return state; }