Quick hack to make NSX-39 (Poke-Miku) USB MIDI device to speak "mbed" from mbed which acts as an USB host.

Dependencies:   FatFileSystem mbed

Fork of MIDI_BlueUSB by Radio Junk Box

Description of the project

This is quick hack to control Poke-miku (NSX-39) from mbed. The mbed acts as an USB host and controls USB MIDI device NSX-39. It speaks "mbed" if you send "s¥n" from virtual USB serial (connected to PC or Mac) or push SW connected to p21. It plays MIDI file "test.mid" on local file-system if you push SW connected to p22. You can find files that I have tested at the bottom. The standard MIDI file support is still preliminary. See TestShell.cpp for the hack. This program is derived from MIDI_BlueUSB (http://mbed.org/users/radiojunkbox/code/MIDI_BlueUSB/) by Radio Junk Box.

ポケミク(NSX-39)を無改造のままmbedから鳴らせるようにしてみました。mbedがUSB hostになって、USB MIDIデバイスのポケミクを鳴らします。mbedのバーチャルシリアル(USBシリアル)にPCからs\nを送るか、p21につないだスイッチを押すとmbedとしゃべります。p22につないだスイッチを押すと、ローカルファイルシステム(.binと同じ場所)に保存した test.mid を再生します。試したファイルは下にある test1.mid と test2.mid です。MIDIファイルのサポートはまだまだ完全とはいえません。

tested MIDI files

Video: Poke-miku speaks `mbed'

Files at this revision

API Documentation at this revision

Comitter:
non
Date:
Tue Apr 29 06:01:52 2014 +0000
Parent:
3:31fbce33c25b
Commit message:
Fix issues when it plays a MIDI file which has multi tracks.

Changed in this revision

TestShell.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r 31fbce33c25b -r cd0d8ce967d8 TestShell.cpp
--- a/TestShell.cpp	Sun Apr 27 07:40:40 2014 +0000
+++ b/TestShell.cpp	Tue Apr 29 06:01:52 2014 +0000
@@ -641,6 +641,10 @@
     ret.p = buf;
 
     while (p < e) {
+        if ((*p & 0x80) == 0) {
+            p ++;
+            continue;
+        }
         unsigned char evt = (*p & 0xf0);
         switch (evt) {
             case 0xd0:
@@ -802,57 +806,83 @@
     for (int i=0; i<mh->tracks; i++) {
         trks[i] = new midiTrack;
         trks[i]->readFile(fp);
+        //  fprintf(stderr, "Track%d: ", i);
+        //  trks[i]->dump();
     }
     fclose(fp);
 
+    int deltaT[32] = {0};
+    struct midiPacket pkt[32];
     for (int i=0; i<mh->tracks; i++) {
-        if (trks[i] == NULL)
+        if (trks[i] == NULL) {
+            pkt[i].len = 0;
             continue;
+        }
         trks[i]->rewind();
+        do {
+            pkt[i] = trks[i]->next();
+        } while (pkt[i].len == 0 && !trks[i]->isEnd());
     }
+        // fprintf(stderr, "%d %d\n", trks[0]->tempo, mh->delta);
+        float waitTime = (float)trks[0]->tempo/(float)mh->delta/1000000.0;
 
     for (;;) {
-        struct midiPacket pkt[32];
-        bool songEnd = true;
+        USBLoop();
 
+        bool songEnd = true;
         for (int i=0; i<mh->tracks; i++) {
-            pkt[i].len = 0;
-
             if (trks[i] == NULL)
                 continue;
-
-            if (!trks[i]->isEnd()) {
-                pkt[i] = trks[i]->next();
+            if (pkt[i].len > 0) {
                 songEnd = false;
             }
         }
         if (songEnd)
             break;
 
-        for (int t=0; ; t += 10) {
+        unsigned char buf[64], *p = buf;
+        int len = 0;
+
+        for (int i=0; i<mh->tracks; i++) {
             USBLoop();
-            bool toNext = true;
-            for (int i=0; i<mh->tracks; i++) {
-                if (pkt[i].len == 0) {
-                    continue;
+            if (pkt[i].len == 0) {
+                continue;
+            }
+            //fprintf(stderr, "%d: %d %d\n", i, deltaT[i], pkt[i].delta);
+            if (deltaT[i] >= pkt[i].delta) {
+#if 1
+                deltaT[i] = 0;
+#else
+                fprintf(stderr, "%d[%d] ", deltaT[i], i);
+                deltaT[i] = 0;
+                for (int j=0; j<pkt[i].len; j++) {
+                    fprintf(stderr, "%02x ", pkt[i].p[j]);
                 }
-                toNext = false;
-                if (t >= pkt[i].delta) {
-                    fprintf(stderr, "%d[%d] ", t, i);
-                    for (int j=0; j<pkt[i].len; j++) {
-                        fprintf(stderr, "%02x ", pkt[i].p[j]);
-                    }
-                    fprintf(stderr, "\n");
+                fprintf(stderr, "\n");
+#endif
+                if ((len + pkt[i].len) > sizeof(buf)) {
                     USBBulkTransfer(NSX39_device, NSX39_endpoint,
-                                    pkt[i].p, pkt[i].len, NULL, NULL);
+                                    buf, len, NULL, NULL);
+                    p = buf;
+                    len = 0;
+                }
+                memcpy(p, pkt[i].p, pkt[i].len);
+                p += pkt[i].len;
+                len += pkt[i].len;
+                if (!trks[i]->isEnd()) {
+                    do {
+                        pkt[i] = trks[i]->next();
+                    } while (pkt[i].len == 0 && !trks[i]->isEnd());
+                } else {
                     pkt[i].len = 0;
                 }
-            }
-            if (toNext)
-                break;
-//    fprintf(stderr, "%f ", (float)trks[0]->tempo/(float)mh->delta/1000000.0);
-            wait((float)trks[0]->tempo/(float)mh->delta/100000.0);
+            } else
+                deltaT[i] ++;
         }
+        if (len > 0)
+            USBBulkTransfer(NSX39_device, NSX39_endpoint,
+                            buf, len, NULL, NULL);
+        wait(waitTime);
     }
 
     for (int i=0; i<mh->tracks; i++) {