Android Question B4A mediaplayer can not play Treble scale sound

Maodge

Member
Licensed User
Hello,
I create a project to play midi files with different music instrument.
and I find not all instrument can play all music note.

I test on huawei honor 8c device, android ver 8.1.0
for example, harmonica(midi instrument 22) can not play tune value bigger than 5D(value 74).
Acoustic Grand Piano(midi instrument 0) can not play tune value bigger than 7E(value 100).
like attached project.
I create a test midi file. begin with music note 4C(value 60) duration time 1 second.
next play from 3C(value 48) to 7G(value 103), every tune play 0.25 second
and end with 4C(value 60) duration time 1 second.

I guess maybe b4A or android default soundfont limited.
I find some java code about how play midi with other sf2 lib.
I don't know any java.
so my question :
1 how to play Treble scale sound in b4a?
2 please give me some advice about change sf2 lib in b4a.

thanks.

below is java code,play midi with
B4X:
bogon:temp donmor$ cat MIDITest.java
import java.io.File;
import java.util.ArrayList;
import javax.sound.midi.*;

public class MIDITest {

    private static MidiDevice midid;

    public static void main(String[] args) {

        try {
            MidiDevice.Info[] vdevs = MidiSystem.getMidiDeviceInfo();//获取所有MIDI设备信息
            ArrayList<MidiDevice.Info> xdevs = new ArrayList<MidiDevice.Info>();//准备筛除一些不能用来播放的设备,用这个ArrayList存放合格的
            for (MidiDevice.Info dev : vdevs) {
                String s = dev.getName();
                try {
                    MidiDevice vc = MidiSystem.getMidiDevice(dev);//启动每个设备试验
                    vc.getReceiver();//直接访问Receiver,如果没有就走catch
                    vc.close();//关闭设备
                } catch (MidiUnavailableException e) {
                    s = "$NORECEIVER";//利用名称筛除没有Receiver的设备
                }
                if (s != "Real Time Sequencer" && s != "$NORECEIVER")//筛除没有Receiver的设备和Real Time Sequencer(这个是音序器的Receiver,用来做MIDI录制的,当然不能要它)
                    xdevs.add(dev);//过检的插进ArrayList里
            }
            MidiDevice.Info[] arrw = new MidiDevice.Info[xdevs.size()];
            MidiDevice.Info[] devs = xdevs.toArray(arrw);//这两句用来把ArrayList转为数组,注意不能直接toArray
            if (args[0].equals("-devlist")) {//读取命令行参数第一位,如果是-devlist的话
                System.out.println("ID    Name    Description    Vendor    Version");
                int i = 0;
                for (MidiDevice.Info dev : devs) {
                    System.out.println(String.valueOf(i) + "    " + dev.getName() + "    " + dev.getDescription() + "    " + dev.getVendor() + "    " + dev.getVersion());
                    i++;
                }
                System.exit(0);//结束
            } else if (args[0].equals("-help")) {
                System.out.println("Usage:    MIDITest [FILE] [OPTION] ...");
                System.out.println("    MIDITest [OPTION]");
                System.out.println("A test application that plays MIDI files.");
                System.out.println("");
                System.out.println("Options:");
                System.out.println("    -dev ID        Use specific device to play the MIDI file. Use ");
                System.out.println("            -devlist option to enquire about device IDs.");
                System.out.println("    -sf2         Load sf2 files into the Gervill Software MIDI ");
                System.out.println("            Synthesizer provided by Java by default. ");
                System.out.println("            Please note that following sf2 files overwrites");
                System.out.println("            previous ones.");
                System.out.println("    -help        Display this help and exit.");
                System.out.println("    -devlist    List available MIDI devices and exit.");
                System.exit(0);//显示帮助并退出
            }
            String arg1 = "";
            String[] arg2 = new String[1];
            arg2[0] = "";//准备读更多参数
            ArrayList<String> arg2s = new ArrayList<String>();
            try {
                arg1 = args[1];
                int i = 0;
                boolean granted = false;
                for (String arg : args) {
                    if (i > 1)
                        arg2s.add(arg);
                    i++;
                }
                String[] arrw2 = new String[arg2s.size()];
                arg2 = arg2s.toArray(arrw2);//读参数,若参数不全则抛异常跳过
            } catch (Exception e) {

            }
            File midif = new File(args[0]);//打开MIDI文件,这里是直接从参数的第一位读取
            Sequence seq = MidiSystem.getSequence(midif);//加载文件到序列(Sequence)中
            Sequencer midip= MidiSystem.getSequencer(!(arg1.equals("-dev") || arg1.equals("-sf2")));//创建一个音序器(Sequencer),即播放器的核心,这里如果传了-dev或-sf2参数,就不自动连接默认设备
            midip.open();//启动音序器
            if (arg1.equals("-dev")) {//检查参数
                midid = MidiSystem.getMidiDevice(devs[Integer.parseInt(arg2[0])]);//获取MIDI设备
                midid.open();//启动MIDI设备
                midip.getTransmitter().setReceiver(midid.getReceiver());//关键的一步,把之前的音序器的Transmitter和MidiDevice的Receiver挂接起来
            } else if (arg1.equals("-sf2")) {
                midid = MidiSystem.getMidiDevice(devs[0]);//获取MIDI设备
                midid.open();//启动MIDI设备
                Synthesizer midis = (Synthesizer) midid;//获取合成器
                for (String sf2 : arg2) {//对每个从参数传来的sf2文件:
                    try {
                        Soundbank sbx = MidiSystem.getSoundbank(new File(sf2));
                        midis.loadAllInstruments(sbx);//顺序加入合成器中
                    } catch (Exception e) {

                    }
                }
                midip.getTransmitter().setReceiver(midid.getReceiver());//关键的一步,把之前的音序器的Transmitter和MidiDevice的Receiver挂接起来
            }
            midip.setSequence(seq);//把序列插入到音序器中
            if (!midip.isRunning()){
                System.out.println("Now Playing...");
                midip.start();//开始播放
            }
            Runtime.getRuntime().addShutdownHook(new Thread() {//加入退出检测线程,Ctrl-C时停止并释放资源
                public void run() {
                    try {
                        System.out.println("[Quit]");
                        if (midip.isRunning())
                            midip.stop();
                        if (midip.isOpen())
                            midip.close();
                        if (midid != null && midid.isOpen())
                            midid.close();//关闭音序器和设备,结束程序
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
            long time = midip.getMicrosecondLength() / 1000;//获取MIDI文件长度
            Thread.sleep(time);//让程序等待,直到播放结束
            if (midip.isRunning())
                midip.stop();
            if (midip.isOpen())
                midip.close();
            if (midid != null && midid.isOpen())
                midid.close();//此六句关闭音序器和设备,程序主体结束
        } catch(Exception e) {
            e.printStackTrace();//处理异常
        }
    }
}
bogon:temp donmor$ java MIDITest 01.mid -sf2 ~/Documents/SGM-180_v1.5.sf2
Now Playing...
^C[Quit]
————————————————
版权声明:本文为CSDN博主「donmor」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/donmor/article/details/87863430
 

Attachments

  • test-midi.zip
    9.8 KB · Views: 167
Top