【Android】Live2D Cubism SDK for Javaのカスタマイズ集
2024/07/19
2024/07/22
📰 アフィリエイト広告を利用しています
はじめに
OpenGLやLive2Dに関する知識はないので、使用するときは自己責任でお願いします。
使用した元のコードは以下のコード参照。忘れたときようのメモ
背景を透明にする
GLSurfaceViewの設定とLAppDelegateのrun()関数を修正する
MainActivity.kt
_glSurfaceView = GLSurfaceView(applicationContext)
_glSurfaceView.setEGLContextClientVersion(2)
_glSurfaceView.apply {
setEGLConfigChooser(8, 8, 8, 8, 16, 0)
holder.setFormat(android.graphics.PixelFormat.TRANSLUCENT)
setZOrderOnTop(true)
}
LAppDelegate.java
public void run() {
// ....
// glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // 透明な背景を指定
}
表示倍率を変更
表示範囲内でモデルのサイズの縮小・拡大
LAppLive2DManager
public void changeScene(int index) {
// ...
// 大きさを3倍
models.get(0).getModelMatrix().scaleRelative(3.0f, 3.0f);
}
表示位置の変更
3倍表示の時1.0fの設定で画面に行ってしまったので値は小さな値で確認する。
LAppLive2DManager
public void changeScene(int index) {
// ...
// 表示位置を移動
models.get(0).getModelMatrix().translateRelative(0f, -0.7f);
}
モーションの実行
現在のモデルを取得し、モーションを再生させる。
val currentModelId = LAppLive2DManager.getInstance().currentModel
val model: LAppModel = LAppLive2DManager.getInstance().getModel(currentModelId)
model.startMotion("LipSync", 0, 100)
リップシンク
以下のvolume変数を変えると口の開き具合が変わる。
範囲は0.0fから1.0f
LAppModel.java
public void update(){
// ...
// 160行目
float value = 0.0f;
}
MediaPlayerとVisualizerを使って再生している音声にシンクする。
LipSyncを作成
LipSync.kt
class LipSync(private val mediaPlayerId: Int) {
private var visualizer: Visualizer? = null
fun start() {
visualizer = Visualizer(mediaPlayerId)
visualizer?.setCaptureSize(Visualizer.getCaptureSizeRange()[1])
val model = LAppLive2DManager.getInstance().getModel(0)
visualizer?.setDataCaptureListener(object : Visualizer.OnDataCaptureListener {
override fun onWaveFormDataCapture(
visualizer: Visualizer,
bytes: ByteArray,
samplingRate: Int
) {
// 波形データの平均値を計算
var sum = 0L
bytes.forEach { value ->
sum += kotlin.math.abs(value.toInt()) // 波形データの絶対値を取得し、合計に加算
}
val average = sum / bytes.size.toDouble() // 平均値を計算
// 平均値を音声の大きさとして利用
var volume =
1 - (average / Byte.MAX_VALUE) // 波形データはバイト型の範囲で表現されるため、最大値で割って正規化する
// 音声の大きさを利用して必要な処理を行う
volume *= 2
if (volume > 1) {
volume = 1.0
}
model.volume = volume.toFloat()
}
override fun onFftDataCapture(
visualizer: Visualizer,
bytes: ByteArray,
samplingRate: Int
) {
}
}, Visualizer.getMaxCaptureRate(), true, true)
visualizer?.setEnabled(true);
}
fun dispose() {
visualizer?.release()
val model = LAppLive2DManager.getInstance().getModel(0)
model.volume = 0.0f
}
}
リップシンクを設定して音声を再生する。
var mediaPlayer = MediaPlayer.create(context, R.row.audio_file).apply {
setAudioAttributes(
AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
.setUsage(AudioAttributes.USAGE_MEDIA)
.build()
)
}
val lipSync = LipSync(mediaPlayer.audioSessionId)
lipSync.start()
mediaPlayer.setOnCompletionListener {
mediaPlayer.release()
mediaPlayer = null
lipSync.dispose()
}
mediaPlayer.start()