【问题标题】:No sound out of an android MIDI driver integrated in Unity3dUnity3d 中集成的 android MIDI 驱动程序没有声音
【发布时间】:2019-08-14 22:26:44
【问题描述】:

我想在 Android 上使用 Unity3d 输出 MIDI 音频。使用开源库,我想我可以正常工作,但设备没有发出声音,也没有任何类型的错误消息/日志。

我正在使用这个库: https://github.com/billthefarmer/mididriver

我已经使用 Android Studio 使用提供的 gradle 项目测试了该库,并且运行良好。

Unity 通过将该库的 AAR 文件拖放到 Assets\Plugins\Android 中来识别它。然后我添加了一个 java 类来包装方法调用, 并创建了一个小的 C# MonoBehaviour 脚本来测试它。我隔离了代码,以便您重现问题。

复制:

  1. 使用 Unity3d 创建一个新的 3d 项目。
  2. 添加一个空的游戏对象。
  3. 将以下 C# 脚本附加到它。
  4. 在 Assets 文件夹中创建文件夹 Plugins\Android。
  5. 在 Android 文件夹中创建一个包含以下 java 代码的新文件。
  6. 添加最新版本的链接库的 AAR 文件。
  7. 构建并将其加载到 Android 设备。

C# 单一行为

每 2 秒发送一条 NOTE_ON 消息,然后在一秒钟后发送一条 NOTE_OFF 消息。 AndroidJavaClass 用于调用库的方法。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MidiDriverDemo : MonoBehaviour
{
    private const string CLASS_PATH = "com.example.driver.AndroidMidiDriver";

    public static readonly float CYCLE_TIME_SEC = 1f;

    private float remainingTime;

    private Dictionary<int, int[]> messages;
    private int currentMessage;

    AndroidJavaClass midiDriver;

    // Start is called before the first frame update
    void Start()
    {
        remainingTime = CYCLE_TIME_SEC;
        currentMessage = 0;
        messages = new Dictionary<int, int[]>() {
            {  0, new int[] { 0x90, 48, 63 } },
            {  1, new int[] { 0x80, 48, 0 } }
        };

        midiDriver = new AndroidJavaClass(CLASS_PATH);
        midiDriver.Call("start");
    }

    // Update is called once per frame
    void Update()
    {
        remainingTime -= Time.deltaTime;
        if(remainingTime <= 0) {
            remainingTime = CYCLE_TIME_SEC;

            midiDriver.Call("send", messages[currentMessage][0],
                messages[currentMessage][1], messages[currentMessage][2]);

            currentMessage++;
            currentMessage %= messages.Count;
        }
    }
}

java 包装器

package com.example.driver;

import org.billthefarmer.mididriver.MidiDriver;

public class AndroidMidiDriver {

    private MidiDriver midi;

    public AndroidMidiDriver(){
        midi = new MidiDriver();
    }

    public void start(){
        if (midi != null) {
            midi.start();
        }
    }

    public void stop() {
        if (midi != null) {
            midi.stop();
        }
    }

    public void send(int command, int noteNumber, int velocity){
        byte[] msg = new byte[3];

        msg[0] = (byte) command;
        msg[1] = (byte) noteNumber;
        msg[2] = (byte) velocity;

        midi.write(msg);
    }
}

所以它编译完美,没有任何警告,并且在设备上运行,但仍然没有声音。音量设置正确。

在我隔离问题之前,对“send”方法的调用使我的应用程序因分段错误而崩溃,所以我猜有些东西正在工作。

所以我认为问题在于:

  • 这不是访问 AAR 的正确方法。
  • 我错过了 Unity 中的一些设置。
  • 问题出在库本身,不太可能,因为它与提供的 gradle 项目独立工作。

欢迎提出任何想法/建议。

【问题讨论】:

    标签: java c# android unity3d midi


    【解决方案1】:

    从 .aar 中提取 jni/armv7a 文件夹中的 libmidi.so 后,删除 java 包装器并将代码更改为以下内容:

    using System.Collections;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using UnityEngine;
    
    public class MidiDriverDemo : MonoBehaviour
    {
        public static readonly float CYCLE_TIME_SEC = 1f;
    
        private float remainingTime;
    
        private Dictionary<int, byte[]> messages;
        private int currentMessage;
    
        [DllImport("midi")]
        private static extern float midi_init();
    
        [DllImport("midi")]
        private static extern float midi_shutdown();
    
        [DllImport("midi")]
        private static extern float midi_write(byte[] msg, int length);
    
        // Start is called before the first frame update
        void Start()
        {
            remainingTime = CYCLE_TIME_SEC;
            currentMessage = 0;
            messages = new Dictionary<int, byte[]>() {
                {  0, new byte[] { 0x90, 48, 100 } },
                {  1, new byte[] { 0x80, 48, 0 } }
            };
    
            midi_init();
        }
    
        // Update is called once per frame
        void Update()
        {
            remainingTime -= Time.deltaTime;
            if(remainingTime <= 0) {
                remainingTime = CYCLE_TIME_SEC;
    
                midi_write(messages[currentMessage], 3);
    
                currentMessage++;
                currentMessage %= messages.Count;
            }
        }
    }
    

    设备上终于有音频输出了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多